package com.zfire.mall.manager.bean.displace.order;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.zfire.mall.manager.bean.admin.AdminUserCom;
import com.zfire.mall.manager.bean.wallet.CustomerWalletBean;
import com.zfire.mall.manager.enums.OrderTypeEnum;
import com.zfire.mall.manager.exception.RemoteServiceException;
import com.zfire.mall.manager.logic.customer.CustomerEnginDepositLogic;
import com.zfire.mall.manager.logic.wallet.WalletLogic;
import com.zfire.mall.manager.plus.entity.*;
import com.zfire.mall.manager.plus.service.EnginOrderItemService;
import com.zfire.mall.manager.plus.service.RetailOrderItemService;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel
public class DisplaceOrderBean extends DisplaceOrder {

    @ApiModelProperty(value = "审批结果 0=驳回 1=通过")
    private boolean examineResult = false;

    @ApiModelProperty(value = "退订说明")
    private String refundNote;

    @ApiModelProperty(value = "置换单明细")
    List<DisplaceOrderItem> items;
    @ApiModelProperty(value = "订单原明细")
    List<DisplaceOrderOriginItem> originItems;

    public void handleRetailOrderInfo(RetailOrder retailOrder, List<RetailOrderItem> retailOrderItems) {
        this.setAdminCompanyId(retailOrder.getAdminCompanyId())
                .setCustomerId(retailOrder.getCustomerId())
                .setCustomerName(retailOrder.getCustomerName())
                .setOrderType(retailOrder.getType() == 1 ? OrderTypeEnum.RETAIL.getKey() : OrderTypeEnum.RETAIL_POLICY.getKey())
                .setOrderNo(retailOrder.getId())
                .setOrderDate(DateUtil.date())
                .setPolicyId(retailOrder.getPolicyId())
                .setPolicyCode(retailOrder.getPolicyCode())
                .setPolicyTitle(retailOrder.getPolicyTitle())
                .setPolicyRemark(retailOrder.getPolicyRemark())
//                .setServiceId(retailOrder.getServiceId())
//                .setServiceName(retailOrder.getServiceName())
        ;

        List<DisplaceOrderOriginItem> originItems = new ArrayList<>();
        for (RetailOrderItem retailOrderItem : retailOrderItems) {
            DisplaceOrderOriginItem displaceOrderOriginItem = new DisplaceOrderOriginItem();
            displaceOrderOriginItem.setRefId(retailOrderItem.getId())
                    .setOrderNo(retailOrder.getId())
                    .setSaleTypeId(retailOrderItem.getSaleTypeId())
                    .setSaleTypeCode(retailOrderItem.getSaleTypeCode())
                    .setSaleTypeName(retailOrderItem.getSaleTypeName())
                    .setMaterialId(retailOrderItem.getMaterialId())
                    .setMaterialNumber(retailOrderItem.getMaterialCode())
                    .setMaterialOldNumber(retailOrderItem.getMaterialOldNumber())
                    .setMaterialName(retailOrderItem.getMaterialName())
                    .setSpecification(retailOrderItem.getSpecification())
                    .setUnit(retailOrderItem.getUnit())
                    .setPrice(retailOrderItem.getPrice())
                    .setQty(retailOrderItem.getQty())
                    .setRebateRate(retailOrderItem.getRebateRate())
                    .setCustomerWalletId(retailOrderItem.getCustomerWalletId())
                    .setCustomerWalletName(retailOrderItem.getCustomerWalletName())
                    .setCustomerWalletId2(retailOrderItem.getCustomerWalletId2())
                    .setCustomerWalletName2(retailOrderItem.getCustomerWalletName2())
                    .setDiscAmount(retailOrderItem.getDiscAmount())
                    .setTotalDiscAmount(retailOrderItem.getTotalDiscAmount())
                    .setTotalAmount(retailOrderItem.getTotalAmount())
                    .setSingleRebateAmount(retailOrderItem.getSingleRebateAmount())
                    .setSinglePayPrice(retailOrderItem.getSinglePayPrice())
                    .setPayAmount(retailOrderItem.getPayAmount())
                    .setPayRebateAmount(retailOrderItem.getPayRebateAmount())
                    .setTax(retailOrderItem.getTax())
                    .setRemark(retailOrderItem.getRemark())
                    .setDisplaceQty(0)
                    .setRefundableQty(retailOrderItem.getRefundableQty());
            originItems.add(displaceOrderOriginItem);
        }
        this.setOriginItems(originItems);
    }

    public void handleEnginOrderInfo(EnginOrder enginOrder, List<EnginOrderItem> enginOrderItems) {
        this.setAdminCompanyId(enginOrder.getAdminCompanyId())
                .setCustomerId(enginOrder.getCustomerId())
                .setCustomerName(enginOrder.getCustomerName())
                .setOrderType(enginOrder.getEnginOrderType())
                .setOrderNo(enginOrder.getEnginOrderNo())
                .setOrderDate(DateUtil.date())
                .setEnginRecordNo(enginOrder.getRefEnginRecordNo())
                .setProjectNo(enginOrder.getRefProjectNo())
                .setProjectName(enginOrder.getRefProjectName())
                .setUseUnit(enginOrder.getRefUseUnit())
                .setInstallAddress(enginOrder.getRefInstallAddress())
                .setTakeDeposit(enginOrder.getTakeDeposit());

        List<DisplaceOrderOriginItem> originItems = new ArrayList<>();
        for (EnginOrderItem enginOrderItem : enginOrderItems) {
            DisplaceOrderOriginItem displaceOrderOriginItem = new DisplaceOrderOriginItem();
            displaceOrderOriginItem.setRefId(enginOrderItem.getId())
                    .setOrderNo(enginOrder.getEnginOrderNo())
                    .setSaleTypeId(enginOrderItem.getSaleTypeId())
                    .setSaleTypeCode(enginOrderItem.getSaleTypeCode())
                    .setSaleTypeName(enginOrderItem.getSaleTypeName())
                    .setMaterialId(enginOrderItem.getMaterialId())
                    .setMaterialNumber(enginOrderItem.getMaterialNumber())
                    .setMaterialOldNumber(enginOrderItem.getMaterialOldNumber())
                    .setMaterialName(enginOrderItem.getMaterialName())
                    .setSpecification(enginOrderItem.getSpecification())
                    .setUnit(enginOrderItem.getUnit())
                    .setPrice(enginOrderItem.getPrice())
                    .setQty(enginOrderItem.getQty())
                    .setRebateRate(enginOrderItem.getRebateRate())
                    .setCustomerWalletId(enginOrderItem.getCustomerWalletId())
                    .setCustomerWalletName(enginOrderItem.getCustomerWalletName())
                    .setCustomerWalletId2(enginOrderItem.getCustomerWalletId2())
                    .setCustomerWalletName2(enginOrderItem.getCustomerWalletName2())
                    .setDiscAmount(enginOrderItem.getDiscAmount())
                    .setTotalDiscAmount(enginOrderItem.getTotalDiscAmount())
                    .setTotalAmount(enginOrderItem.getTotalAmount())
                    .setSingleRebateAmount(enginOrderItem.getSingleRebateAmount())
                    .setSinglePayPrice(enginOrderItem.getSinglePayPrice())
                    .setPayAmount(enginOrderItem.getPayAmount())
                    .setPayRebateAmount(enginOrderItem.getPayRebateAmount())
                    .setTax(enginOrderItem.getTax())
                    .setRemark(enginOrderItem.getRemark())
                    .setDisplaceQty(0)
                    .setRefundableQty(enginOrderItem.getRefundableQty());
            originItems.add(displaceOrderOriginItem);
        }
        this.setOriginItems(originItems);
    }

    public DisplaceOrder handleAddOrderInfo(AdminUserCom adminUser) {
        DisplaceOrder displaceOrder = new DisplaceOrder();
        BeanUtils.copyProperties(this, displaceOrder);
        displaceOrder.setCreateName(adminUser.getNickName())
                .setUpdateName(adminUser.getNickName());
        return displaceOrder;
    }

    public void handleAddOriginItem() {
        if (CollectionUtil.isEmpty(this.originItems)) {
            throw new RemoteServiceException("置换的原产品明细不能为空");
        }
        for (DisplaceOrderOriginItem originItem : this.originItems) {
            if (StringUtils.isBlank(originItem.getRefId())) {
                throw new RemoteServiceException("原单订单" + originItem.getMaterialName() + "产品缺唯一标记");
            }
            originItem.setParentId(this.getDisplaceOrderId())
                    .setOrderNo(this.getOrderNo());
        }
    }

    public void handleAddOrderItem(WalletLogic walletLogic, CustomerEnginDepositLogic customerEnginDepositLogic) {
        if (CollectionUtil.isEmpty(this.items)) {
            throw new RemoteServiceException("置换的产品明细不能为空");
        }

        //查询钱包名称
        List<CustomerWalletBean> customerWalletBeans = walletLogic.queryWalletByCustomerId(this.getCustomerId(), null);
        Map<String, CustomerWalletBean> walletMap = customerWalletBeans.stream()
                .collect(Collectors.toMap(CustomerWalletBean::getCustomerWalletId, v -> v));

        BigDecimal depositRate = this.queryOrderTakeDeposit(customerEnginDepositLogic);
        BigDecimal zero = new BigDecimal("0");
        int depositCompare = depositRate.compareTo(zero);

        for (int i = 0; i < this.items.size(); i++) {
            DisplaceOrderItem item = this.items.get(i);
            if (StringUtils.isBlank(item.getSaleTypeId())) {
                throw new RemoteServiceException("第" + (i+1) + "行置换的产品销售类型不能为空");
            }
            if (StringUtils.isBlank(item.getMaterialId())) {
                throw new RemoteServiceException("第" + (i+1) + "行置换的产品不能为空");
            }
            if (Objects.isNull(item.getQty()) || item.getQty() < 1) {
                throw new RemoteServiceException("第" + (i+1) + "行置换的产品数量不能少于1");
            }
            if (Objects.isNull(item.getPrice())) {
                throw new RemoteServiceException("第" + (i+1) + "行置换的产品单价不能为空");
            }

            // 现金钱包
            CustomerWalletBean amountCustomerWallet = walletMap.get(item.getCustomerWalletId());
            // 返利钱包
            CustomerWalletBean rebateCustomerWallet = walletMap.get(item.getCustomerWalletId2());
            if(amountCustomerWallet == null){
                throw new RemoteServiceException("请选择现金钱包");
            }
            // 单价
            BigDecimal price = item.getPrice();
            // 折扣价
            BigDecimal discAmount = Objects.isNull(item.getDiscAmount()) ? BigDecimal.valueOf(0) : item.getDiscAmount();
            // 数量
            BigDecimal qty = BigDecimal.valueOf(item.getQty());
            // 总价
            BigDecimal totalAmount = price.multiply(qty);
            // 总返利价格
            BigDecimal totalRebateAmount = new BigDecimal(0);
            if(rebateCustomerWallet != null) {
                List<WalletRebateSaleType> walletRebateSaleTypes = rebateCustomerWallet.getWalletRaleTypes().stream()
                        .filter(v -> v.getSaleTypeId().equals(item.getSaleTypeId())).collect(Collectors.toList());
                if(CollectionUtils.isEmpty(walletRebateSaleTypes)){
                    throw new RemoteServiceException("返利钱包不符合销售类型");
                }
                item.setRebateRate(walletRebateSaleTypes.get(0).getRebateRate());
                totalRebateAmount = item.getRebateRate().multiply(totalAmount);
            }
            // 总折扣价格
            BigDecimal totalDiscAmount = discAmount.multiply(qty);
            // 实际使用返利金额
            BigDecimal payRebateAmount = totalRebateAmount;
            if(rebateCustomerWallet != null && rebateCustomerWallet.getAmount().doubleValue() < totalRebateAmount.doubleValue()){
                payRebateAmount = rebateCustomerWallet.getAmount();
            }
            //实际支付价格
            BigDecimal payAmount = totalAmount
                    .subtract(totalDiscAmount)
                    .subtract(payRebateAmount);

            item.setParentId(this.getDisplaceOrderId());
            item.setOrderNo(this.getOrderNo());
            item.setCustomerWalletName(amountCustomerWallet.getName());
            item.setCustomerWalletNumber(amountCustomerWallet.getWalletNumber());
            if(rebateCustomerWallet != null) {
                item.setCustomerWalletName2(rebateCustomerWallet.getName());
            }
            item.setTotalAmount(totalAmount);
            item.setRebateAmount(totalRebateAmount.doubleValue() < 0?BigDecimal.valueOf(0) : totalRebateAmount);
            item.setPayAmount(payAmount.doubleValue() < 0 ? BigDecimal.valueOf(0):payAmount);
            item.setTotalDiscAmount(totalDiscAmount);
            item.setPayRebateAmount(payRebateAmount);
            item.setSingleRebateAmount(payRebateAmount.divide(qty,6, RoundingMode.HALF_UP));
            item.setSinglePayPrice(item.getPayAmount().divide(qty,6, RoundingMode.HALF_UP));
            item.setRefundableQty(item.getQty());
            // 计算产品押金比例
            item.setDepositRate(depositRate);
            item.setSingleDepositAmount(depositCompare >= 0 ? item.getSinglePayPrice().multiply(depositRate) : zero);
            item.setTotalDepositAmount(depositCompare >= 0 ? item.getSingleDepositAmount().multiply(qty) : zero);

            item.setOrderNo(this.getOrderNo());
        }
    }

    private BigDecimal queryOrderTakeDeposit(CustomerEnginDepositLogic customerEnginDepositLogic) {
        if (Objects.nonNull(this.getTakeDeposit()) && !this.getTakeDeposit()) {
            // 查询押金比例
            return customerEnginDepositLogic.findCustomerDepositRate(this.getCustomerId());
        }
        return new BigDecimal("0");
    }

    public void updOriginRefundableQty(RetailOrderItemService retailOrderItemService,
                                       EnginOrderItemService enginOrderItemService, DisplaceOrderOriginItem item) {
        String orderNo = item.getOrderNo();
        if (orderNo.contains("LS")
                || orderNo.contains("ZC")) {
            RetailOrderItem retailOrderItem = retailOrderItemService.lambdaQuery()
                    .eq(RetailOrderItem::getId, item.getRefId())
                    .eq(RetailOrderItem::getMaterialId, item.getMaterialId())
                    .eq(RetailOrderItem::getSaleTypeId, item.getSaleTypeId())
                    .one();
            if (retailOrderItem.getRefundableQty() - item.getDisplaceQty() < 0) {
                throw new RemoteServiceException("原单订单" + item.getMaterialName() + "产品可退置换数量不足");
            }

            retailOrderItem.setRefundableQty(retailOrderItem.getRefundableQty() - item.getDisplaceQty());
            retailOrderItem.updateById();
        } else {
            EnginOrderItem enginOrderItem = enginOrderItemService.lambdaQuery()
                    .eq(EnginOrderItem::getId, item.getRefId())
                    .eq(EnginOrderItem::getMaterialId, item.getMaterialId())
                    .eq(EnginOrderItem::getSaleTypeId, item.getSaleTypeId())
                    .one();
            if (enginOrderItem.getRefundableQty() - item.getDisplaceQty() < 0) {
                throw new RemoteServiceException("原单订单" + item.getMaterialName() + "产品可退置换数量不足");
            }

            enginOrderItem.setRefundableQty(enginOrderItem.getRefundableQty() - item.getDisplaceQty());
            enginOrderItem.updateById();
        }
    }
}
