package com.zfire.mall.manager.logic.ship;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zfire.mall.manager.bean.ExcelData;
import com.zfire.mall.manager.bean.admin.AdminUserCom;
import com.zfire.mall.manager.bean.engin.deposit.DepositManageRecordBean;
import com.zfire.mall.manager.bean.engin.order.EnginOrderBean;
import com.zfire.mall.manager.bean.engin.order.EnginOrderItemBean;
import com.zfire.mall.manager.bean.invoice.InvoiceApplicationOrderRequest;
import com.zfire.mall.manager.bean.ship.*;
import com.zfire.mall.manager.bean.wallet.CustomerWalletAmountBean;
import com.zfire.mall.manager.commonmapper.ShipMapper;
import com.zfire.mall.manager.enums.OrderTypeEnum;
import com.zfire.mall.manager.exception.RemoteServiceException;
import com.zfire.mall.manager.logic.common.CommonLogic;
import com.zfire.mall.manager.logic.engin.deposit.DepositManageLogic;
import com.zfire.mall.manager.logic.invoice.InvoiceLogic;
import com.zfire.mall.manager.logic.retail.RetailOrderLogic;
import com.zfire.mall.manager.logic.stock.StockCommonLogic;
import com.zfire.mall.manager.logic.wallet.WalletLogic;
import com.zfire.mall.manager.plus.entity.*;
import com.zfire.mall.manager.plus.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author change
 */
@Service
@Slf4j
public class RetreatLogic {

    @Autowired
    ShipMapper shipMapper;

    @Autowired
    RetailOrderLogic retailOrderLogic;

    @Autowired
    StockCommonLogic stockCommonLogic;

    @Autowired
    RetailOrderItemService retailOrderItemService;

    @Autowired
    RetailOrderService retailOrderService;

    @Autowired
    InvoiceApplicationOrderService invoiceApplicationOrderService;

    @Autowired
    InvoiceApplicationService invoiceApplicationrService;

    @Autowired
    InvoiceLogic invoiceLogic;

    @Autowired
    EnginOrderItemService enginOrderItemService;

    @Autowired
    WalletLogic walletLogic;

    @Autowired
    DisplaceOrderItemService displaceOrderItemService;

    @Autowired
    CommonLogic commonLogic;

    @Autowired
    CustomerWalletService customerWalletService;

    @Autowired
    EnginOrderService enginOrderService;


    @Autowired
    DepositManageLogic depositManageLogic;

    public IPage<RetreatDocumentBean> list(String retreatOrderNo, String customerName, String materialName, String specification, String startTime,
                                           String endTime, String customerNumber, Integer pageNum, Integer pageSize) {

        AdminUserCom adminUser = commonLogic.getAdminUser();
        String customerId = adminUser.getIsCustomer() ? adminUser.getCustomerId() : "";

        IPage<RetreatDocumentBean> retreatDocumentBeanIPage = shipMapper.listRetreat(new Page<>(pageNum, pageSize), retreatOrderNo, customerName, materialName, specification, startTime, endTime,
                customerNumber, customerId, adminUser.getServiceIds(),adminUser.getK3CategoryIds());
        return retreatDocumentBeanIPage;
    }

    public RetreatDocumentDetail detail(String id) {
        return shipMapper.detail(id);
    }

    public IPage<RetreatInvoiceBean> listInvoice(String id, String customerId, Integer pageNum, Integer pageSize) {

        AdminUserCom adminUser = commonLogic.getAdminUser();

        IPage<RetreatInvoiceBean> retreatInvoiceBeanIPage = shipMapper.listInvoice(new Page<>(pageNum, pageSize), id, customerId, adminUser.getServiceIds());
        return retreatInvoiceBeanIPage;
    }

    @Transactional(rollbackFor = Exception.class)
    public void add(RetreatDocumentRequest retreatDocumentRequest, HttpServletRequest request) throws Exception {
        if (CollectionUtils.isEmpty(retreatDocumentRequest.getRetreatDocumentOrder()))
            throw new RemoteServiceException("退货单未有退货产品");

        retreatDocumentRequest.insert();

        String customer = null;

        //退款操作
        for (RetreatDocumentOrderRequest retreatDocumentOrderRequest : retreatDocumentRequest.getRetreatDocumentOrder()) {


            InvoiceApplicationOrder invoiceOrder = invoiceApplicationOrderService.getById(retreatDocumentOrderRequest.getInvoiceOrderId());
            InvoiceApplication invoiceApplication = invoiceApplicationrService.getById(invoiceOrder.getInvoiceId());

            if (customer == null)
                customer = invoiceApplication.getCustomerId();
            if (!customer.equals(invoiceApplication.getCustomerId()))
                throw new RemoteServiceException("只能退相同经销商的申请发货单");

            RetreatDocumentOrder retreatDocumentOrder = BeanUtil.toBean(invoiceOrder, RetreatDocumentOrder.class);

            if (invoiceOrder.getRefundableQty() < retreatDocumentOrderRequest.getNum()) {
                throw new RemoteServiceException("机型:" + invoiceOrder.getMaterialName() + "退货数量不可大于可退数量");
            }

            retreatDocumentRequest.setCustomerId(invoiceApplication.getCustomerId());
            retreatDocumentRequest.setCustomerName(invoiceApplication.getCustomerName());
            retreatDocumentRequest.setCustomerNumber(invoiceApplication.getCustomerNumber());

            //添加数据
            retreatDocumentOrder.setCorrespondId(retreatDocumentOrderRequest.getCorrespondId());
            retreatDocumentOrder.setCorrespondName(retreatDocumentOrderRequest.getCorrespondName());
            retreatDocumentOrder.setNum(retreatDocumentOrderRequest.getNum());
            retreatDocumentOrder.setInvoiceOrderId(invoiceOrder.getId());
            retreatDocumentOrder.setRemark(retreatDocumentOrderRequest.getRemark());
            retreatDocumentOrder.setAfterTaxPrice(invoiceOrder.getAfterTaxPrice());
            retreatDocumentOrder.setPrice(invoiceOrder.getPrice());
            retreatDocumentOrder.setNoTotalAmount(invoiceOrder.getNoTotalAmount().divide(new BigDecimal(Convert.toStr(invoiceOrder.getRefundableQty())),BigDecimal.ROUND_CEILING)
                    .multiply(new BigDecimal(Convert.toStr(retreatDocumentOrder.getNum()))));
            retreatDocumentOrder.setPayRebateAmount(invoiceOrder.getPayRebateAmount().divide(new BigDecimal(Convert.toStr(invoiceOrder.getRefundableQty())),BigDecimal.ROUND_CEILING)
                    .multiply(new BigDecimal(Convert.toStr(retreatDocumentOrder.getNum()))));

            retreatDocumentOrder.setPayAmount(invoiceOrder.getSinglePayPrice().multiply(new BigDecimal(Convert.toStr(retreatDocumentOrder.getNum()))));
            retreatDocumentOrder.setTotalAmount(invoiceOrder.getPrice().multiply(new BigDecimal(Convert.toStr(retreatDocumentOrder.getNum()))));

            retreatDocumentOrder.setTotalDiscAmount(invoiceOrder.getDiscAmount().multiply(new BigDecimal(Convert.toStr(retreatDocumentOrder.getNum()))));
            retreatDocumentOrder.setTax(invoiceOrder.getTax());
            retreatDocumentOrder.setRetreatId(retreatDocumentRequest.getId());
            retreatDocumentOrder.setId(null);
            retreatDocumentOrder.insert();


            //维护可退数量
            invoiceOrder.setRefundableQty(invoiceOrder.getRefundableQty() - retreatDocumentOrder.getNum());
            invoiceOrder.setRetiredQty(invoiceOrder.getRetiredQty() + retreatDocumentOrder.getNum());
            invoiceOrder.setPayAmount(invoiceOrder.getPayAmount().subtract(retreatDocumentOrder.getPayAmount()));
            invoiceOrder.setNoTotalAmount(invoiceOrder.getNoTotalAmount().subtract(retreatDocumentOrder.getNoTotalAmount()));
            invoiceOrder.setPayRebateAmount(invoiceOrder.getPayRebateAmount().subtract(retreatDocumentOrder.getPayRebateAmount()));
            invoiceOrder.updateById();

            //1，零售订单退单
            if (retreatDocumentOrder.getOrderType().equals("RETAIL") || retreatDocumentOrder.getOrderType().equals("RETAIL_POLICY"))
                retailOrderLogic.refund(retreatDocumentRequest.getId(), invoiceOrder.getOrderId(), retreatDocumentOrder.getNum(), "退货单退单");

            //2，工程订单退单
            if (retreatDocumentOrder.getOrderType().equals("TRADE") || retreatDocumentOrder.getOrderType().equals("HOME"))
                refundEngin(retreatDocumentRequest, retreatDocumentOrder, invoiceOrder.getOrderId(), retreatDocumentOrder.getNum(), invoiceOrder.getOrderType());

            //3置换单退单
            if (retreatDocumentOrder.getOrderType().equals("PERMU_HOME") || retreatDocumentOrder.getOrderType().equals("PERMU_TRADE") || retreatDocumentOrder.getOrderType().equals("PERMU_RETAIL") || retreatDocumentOrder.getOrderType().equals("PERMU_RETAIL_POLICY"))
                refundDisplace(retreatDocumentRequest, retreatDocumentOrder, invoiceOrder.getOrderId(), retreatDocumentOrder.getNum(), invoiceOrder.getOrderType());

            retreatDocumentRequest.setRetreatTime(new Date());
            retreatDocumentRequest.updateById();

        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void refundEngin(RetreatDocumentRequest retreatDocumentRequest, RetreatDocumentOrder retreatDocumentOrder, String retailOrderItemId, Integer tdQtyRefund, String orderType) throws Exception {
        String enginName = orderType.equals(OrderTypeEnum.HOME.getKey()) ? "家用" : "商用";
        EnginOrderItem enginOrderItem = enginOrderItemService.getById(retailOrderItemId);


        if (tdQtyRefund == null || tdQtyRefund == 0) {
            return;
        }

        BigDecimal tdQty = BigDecimal.valueOf(tdQtyRefund);
        //需要退的钱
        BigDecimal refundPayAmount = enginOrderItem.getSinglePayPrice().multiply(tdQty);
        //需要退的返利金额
        BigDecimal refundRebateAmount = enginOrderItem.getSingleRebateAmount().multiply(tdQty);
        //返利单退款
        List<CustomerWalletAmountBean> customerWalletAmountBeans = new ArrayList<>();
        if (refundRebateAmount.doubleValue() > 0) {
            customerWalletAmountBeans.add(new CustomerWalletAmountBean(enginOrderItem.getCustomerWalletId2(), refundRebateAmount, enginOrderItem.getRemark(),
                    enginName + "工程申请发货订单返利退款-退货单", retreatDocumentRequest.getRetreatTime(), retreatDocumentOrder.getOrderId(), 2, "add"));

        }
        // 现金退款
        if (refundPayAmount.doubleValue() > 0) {
            customerWalletAmountBeans.add(new CustomerWalletAmountBean(enginOrderItem.getCustomerWalletId(), refundPayAmount, enginOrderItem.getRemark(),
                    enginName + "工程发货申请发货订单退款-退货单", retreatDocumentRequest.getRetreatTime(), retreatDocumentOrder.getOrderId(), 2, "add"));
        }
        walletLogic.doWalletAmount(customerWalletAmountBeans);


        List<DepositManageRecordBean> depositManageRecordList = new ArrayList<>();

        //工程退押金
        EnginOrderItem orderItem = enginOrderItemService.getById(retailOrderItemId);
        EnginOrder enginOrder = enginOrderService.getById(orderItem.getParentId());

        if (retreatDocumentOrder.getOrderType().equals("HOME") || retreatDocumentOrder.getOrderType().equals("PERMU_HOME")) {
            DepositManageRecordBean depositManageRecordBean = new DepositManageRecordBean();
            depositManageRecordBean.handleEnginOrderItem(enginOrder, orderItem, tdQtyRefund, orderItem.getSingleDepositAmount().multiply(tdQty));
            depositManageRecordList.add(depositManageRecordBean);
        }
        if (CollectionUtil.isNotEmpty(depositManageRecordList))
        depositManageLogic.reduceDepositAmount(enginOrder.getRefEnginRecordNo(), depositManageRecordList);
    }

    @Transactional(rollbackFor = Exception.class)
    public void refundDisplace(RetreatDocumentRequest retreatDocumentRequest, RetreatDocumentOrder retreatDocumentOrder, String retailOrderItemId, Integer tdQtyRefund, String orderType) throws Exception {
        DisplaceOrderItem displaceOrderItem = displaceOrderItemService.getById(retailOrderItemId);


        if (tdQtyRefund == null || tdQtyRefund == 0) {
            return;
        }

        BigDecimal tdQty = BigDecimal.valueOf(tdQtyRefund);
        //需要退的钱
        BigDecimal refundPayAmount = displaceOrderItem.getSinglePayPrice().multiply(tdQty);
        //需要退的返利金额
        BigDecimal refundRebateAmount = displaceOrderItem.getSingleRebateAmount().multiply(tdQty);


        //返利单退款
        List<CustomerWalletAmountBean> customerWalletAmountBeans = new ArrayList<>();
        if (refundRebateAmount.doubleValue() > 0) {
            customerWalletAmountBeans.add(new CustomerWalletAmountBean(displaceOrderItem.getCustomerWalletId2(), refundRebateAmount, displaceOrderItem.getRemark(),
                    "置换单工程申请发货订单返利退款-退货单", retreatDocumentRequest.getRetreatTime(), retreatDocumentOrder.getOrderId(), 2, "add"));

        }
        // 现金退款
        if (refundPayAmount.doubleValue() > 0) {
            customerWalletAmountBeans.add(new CustomerWalletAmountBean(displaceOrderItem.getCustomerWalletId(), refundPayAmount, displaceOrderItem.getRemark(),
                    "置换单工程发货申请发货订单退款-退货单", retreatDocumentRequest.getRetreatTime(), retreatDocumentOrder.getOrderId(), 2, "add"));
        }

        walletLogic.doWalletAmount(customerWalletAmountBeans);
    }

    /**
     * 退货单数据导出
     *
     * @param retreatDocumentBeans
     * @return
     */
    public ExcelData export(List<RetreatDocumentBean> retreatDocumentBeans) {
        String[] titles = new String[]{"退换单号", "退货日期", "仓库", "经销商", "产品名称",
                "规格型号", "价税合计", "无税金额", "无税单价", "数量", "备注"};
        List<List<Object>> rows = new ArrayList<>();
        for (RetreatDocumentBean retreatDocumentBean : retreatDocumentBeans) {
            List<Object> row = new ArrayList<>();
            row.add(retreatDocumentBean.getOrderId());
            row.add(DateUtil.formatDate(retreatDocumentBean.getRetreatTime()));
            row.add(retreatDocumentBean.getCorrespondName());
            row.add(retreatDocumentBean.getCustomerName());
            row.add(retreatDocumentBean.getMaterialName());
            row.add(retreatDocumentBean.getSpecification());
            row.add(retreatDocumentBean.getPrice());
            row.add(retreatDocumentBean.getNoTotalAmount());
            row.add(retreatDocumentBean.getAfterTaxPrice());
            row.add(retreatDocumentBean.getNum());
            row.add(retreatDocumentBean.getRemark());

            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setRows(rows);
        excelData.setTitles(Arrays.asList(titles));
        return excelData;
    }


}
