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


import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUnit;
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.sale.StorageFeeBean;
import com.zfire.mall.manager.commonmapper.SaleOrderMapper;
import com.zfire.mall.manager.constant.Constant;
import com.zfire.mall.manager.enums.ExamineStatusEnum;
import com.zfire.mall.manager.enums.OrderTypeStatusEnum;
import com.zfire.mall.manager.logic.common.CommonLogic;
import com.zfire.mall.manager.plus.entity.EnginOrder;
import com.zfire.mall.manager.plus.entity.InvoiceApplicationOrder;
import com.zfire.mall.manager.plus.entity.RetailOrder;
import com.zfire.mall.manager.plus.entity.SalesOrder;
import com.zfire.mall.manager.plus.mapper.SalesOrderMapper;
import com.zfire.mall.manager.plus.service.EnginOrderService;
import com.zfire.mall.manager.plus.service.InvoiceApplicationOrderService;
import com.zfire.mall.manager.plus.service.RetailOrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
public class StorageFeeLogic {

    @Autowired
    CommonLogic commonLogic;

    @Autowired
    SaleOrderMapper saleOrderMapper;

    @Autowired
    InvoiceApplicationOrderService invoiceApplicationOrderService;

    @Autowired
    RetailOrderService retailOrderService;

    @Autowired
    EnginOrderService enginOrderService;




    public IPage<StorageFeeBean> listStorageFee(List<String> categoryNum,String approvalStartTime, String approvalEndTime, String saleExamineStatus, String saleStartTime, String saleEndTime, String invoiceStartTime, String invoiceEndTime, String mainOrderId, List<String> id, List<String> orderNo, String materialNumber, String customerName,
                                                List<String> correspondId, String specification, String materialName, String customerNumber, String startTime, String endTime, Integer pageNum,
                                                Integer pageSize) {

        AdminUserCom adminUser = commonLogic.getAdminUser();
        String customerId = adminUser.getIsCustomer() ? adminUser.getCustomerNumber() : customerNumber;

        Integer count = saleOrderMapper.listStorageFeeCount(categoryNum,approvalStartTime, approvalEndTime,
                saleExamineStatus, saleStartTime, saleEndTime, invoiceStartTime, invoiceEndTime, mainOrderId, id, materialNumber, orderNo,
                customerName, correspondId, specification, materialName, customerId, startTime, endTime, adminUser.getServiceIds(),
                adminUser.getAdminUserId(), adminUser.getK3CategoryIds());

        IPage<StorageFeeBean> list = saleOrderMapper.listStorageFee(new Page<>(pageNum, pageSize,false), categoryNum,approvalStartTime, approvalEndTime,
                saleExamineStatus, saleStartTime, saleEndTime, invoiceStartTime, invoiceEndTime, mainOrderId, id, materialNumber, orderNo,
                customerName, correspondId, specification, materialName, customerId, startTime, endTime, adminUser.getServiceIds(),
                adminUser.getAdminUserId(), adminUser.getK3CategoryIds());

        list.setTotal(count);

        if (CollectionUtils.isEmpty(list.getRecords()))
            return new Page<>();


        List<String> collect1 = list.getRecords().stream().map(StorageFeeBean::getOrderId).collect(Collectors.toList());
        List<String> mainOrderIds = list.getRecords().stream().map(StorageFeeBean::getMainOrderId).collect(Collectors.toList());

        List<InvoiceApplicationOrder> listInvoice = invoiceApplicationOrderService.lambdaQuery()
                .in(InvoiceApplicationOrder::getOrderId,collect1)
                .select(InvoiceApplicationOrder::getOrderId, InvoiceApplicationOrder::getRefundableQty).list();

        List<RetailOrder> retailOrderItems = retailOrderService.lambdaQuery()
                .select(RetailOrder::getId,RetailOrder::getExamineTime)
                .in(RetailOrder::getId, mainOrderIds).list();

        List<EnginOrder> enginOrderList = enginOrderService.lambdaQuery()
                .select(EnginOrder::getEnginOrderNo,EnginOrder::getConfirmTime,EnginOrder::getRefUseUnit)
                .in(EnginOrder::getEnginOrderNo, mainOrderIds).list();

        for (StorageFeeBean record : list.getRecords()) {
            List<InvoiceApplicationOrder> collect = listInvoice.stream()
                    .filter(item -> item.getOrderId().equals(record.getOrderId()))
                    .collect(Collectors.toList());

            List<RetailOrder> retailOrderList = retailOrderItems.stream()
                    .filter(item -> item.getId().equals(record.getMainOrderId()))
                    .collect(Collectors.toList());

            List<EnginOrder> enginOrders = enginOrderList.stream()
                    .filter(item -> item.getEnginOrderNo().equals(record.getMainOrderId()))
                    .collect(Collectors.toList());

            if (!CollectionUtils.isEmpty(retailOrderList)){
                RetailOrder retailOrder = retailOrderList.get(0);
                record.setExamineTime(DateUtil.format(retailOrder.getExamineTime(),"yyyy-MM-dd HH:mm:ss"));
            }else {
                EnginOrder enginOrder = enginOrders.get(0);
                record.setExamineTime(DateUtil.format(enginOrder.getConfirmTime(),"yyyy-MM-dd HH:mm:ss"));
                record.setRefUseUnit(enginOrder.getRefUseUnit());
            }



            record.setSendQty(record.getQty() - collect.stream().mapToInt(InvoiceApplicationOrder::getRefundableQty).sum());

            /*
             * 合计=现金+返利+格力折扣
             *发货金额=合计/数量*发货数量
             *起算日期：=预留日期与发货审核日期取小值（取早），然后+3天
             *结算日期：=出库审核时间
             *计算天数：=结算日期-起算日期+1天
             *仓租：=如果计算天数小于等于15天，发货金额*0.003*计算天数，否则发货金额*0.004*计算天数
             * */

            record.setShipmentAmount(record.getTotalAmount());
            if (record.getReservedCreateTime() != null && record.getApprovalTime() != null)
                record.setStartCalculationTime(record.getReservedCreateTime().before(record.getApprovalTime()) ? DateUtil.offset(record.getReservedCreateTime(), DateField.DAY_OF_MONTH, 3) : DateUtil.offset(record.getApprovalTime(), DateField.DAY_OF_MONTH, 3));
            else if (record.getReservedCreateTime() != null && record.getApprovalTime() == null)
                record.setStartCalculationTime(DateUtil.offset(record.getReservedCreateTime(), DateField.DAY_OF_MONTH, 3));
            else
                record.setStartCalculationTime(DateUtil.offset(record.getApprovalTime(), DateField.DAY_OF_MONTH, 3));

            record.setEndCalculationTime(record.getSalesApprovalTime());
            if (record.getEndCalculationTime() == null || StringUtils.isEmpty(record.getSalesExamineStatus()) || !record.getSalesExamineStatus().equals(ExamineStatusEnum.OK.toString()))
                continue;
            if ( DateUtil.parse(DateUtil.format(record.getStartCalculationTime(), "yyyy-MM-dd"))
                    .compareTo(DateUtil.parse(DateUtil.format(record.getEndCalculationTime(), "yyyy-MM-dd"),"yyyy-MM-dd")) > 0 )
                continue;
            record.setCalculationDays(Convert.toInt(DateUtil.between( DateUtil.parse(DateUtil.format(record.getStartCalculationTime(), "yyyy-MM-dd"),"yyyy-MM-dd")
                    , DateUtil.parse(DateUtil.format(record.getEndCalculationTime(), "yyyy-MM-dd"),"yyyy-MM-dd"), DateUnit.DAY)) + 1);
            if (record.getCalculationDays() > 0) {
                record.setWarehouseRent((record.getCalculationDays() < 15 ?
                        record.getShipmentAmount().multiply(Constant.STORAGE_FEE_SHENGHUO_ONE) : record.getShipmentAmount().multiply(Constant.STORAGE_FEE_SHENGHUO_TWO))
                        .multiply(new BigDecimal(record.getCalculationDays())));
            }

        }
        return list;
    }


    public ExcelData listStorageFeeExport(List<StorageFeeBean> records) {
        String[] titles = new String[]{"订单类型", "订单号", "订单日期", "订单审核时间", "预留单日期", "预留单号", "发货单号","使用单位",
                "发货单日期", "发货单审核时间", "出库状态", "出库审核时间", "出库审核人", "仓库", "客户编码", "客户名称",
                "存货编码", "规格型号", "订单数量", "价税合计", "返利金额","格力折扣额", "合计", "发货数量", "钱包", "钱包对应业务", "金蝶部门", "发货金额", "起算日期", "结算日期",
                "计算天数", "仓租金额","存货类别"};
        List<List<Object>> rows = new ArrayList<>();
        for (StorageFeeBean storageFeeBean : records) {
            List<Object> row = new ArrayList<>();
            row.add(OrderTypeStatusEnum.valueOf(storageFeeBean.getOrderType()).getMsg());
            row.add(storageFeeBean.getMainOrderId());
            row.add(storageFeeBean.getTheTime());
            row.add(storageFeeBean.getExamineTime());
            row.add(DateUtil.format(storageFeeBean.getReservedCreateTime(),"yyyy-MM-dd HH:mm:ss"));
            row.add(storageFeeBean.getReservedId());
            row.add(storageFeeBean.getInvoiceId());
            row.add(storageFeeBean.getRefUseUnit());
            row.add(DateUtil.format(storageFeeBean.getOrderTime(), "yyyy-MM-dd HH:mm:ss"));
            row.add(DateUtil.format(storageFeeBean.getApprovalTime(), "yyyy-MM-dd HH:mm:ss"));
            row.add(!StringUtils.isEmpty(storageFeeBean.getSalesExamineStatus()) && storageFeeBean.getSalesExamineStatus().equals("OK") ? "已审核" : "未审核");
            row.add(!StringUtils.isEmpty(storageFeeBean.getSalesExamineStatus()) && storageFeeBean.getSalesExamineStatus().equals("OK") ? DateUtil.format(storageFeeBean.getSalesApprovalTime(), "yyyy-MM-dd HH:mm:ss") : "");
            row.add(!StringUtils.isEmpty(storageFeeBean.getSalesExamineStatus()) && storageFeeBean.getSalesExamineStatus().equals("OK") ? storageFeeBean.getSalesApprovalName() : "");
            row.add(storageFeeBean.getCorrespondName());
            row.add(storageFeeBean.getCustomerNumber());
            row.add(storageFeeBean.getCustomerName());
            row.add(storageFeeBean.getMaterialCode());
            row.add(storageFeeBean.getSpecification());
            row.add(storageFeeBean.getQty());
            row.add(storageFeeBean.getPayAmount());
            row.add(storageFeeBean.getPayRebateAmount());
            row.add(storageFeeBean.getTotalDiscAmount());
            row.add(storageFeeBean.getTotalAmount());
            row.add(storageFeeBean.getRefundableQty());
            row.add(storageFeeBean.getCustomerWalletName());
            row.add(storageFeeBean.getServiceName());
            row.add(storageFeeBean.getK3OrgNumber());
            row.add(storageFeeBean.getShipmentAmount());
            row.add(DateUtil.format(storageFeeBean.getStartCalculationTime(), "yyyy-MM-dd HH:mm:ss"));
            row.add(DateUtil.format(storageFeeBean.getEndCalculationTime(), "yyyy-MM-dd HH:mm:ss"));
            row.add(storageFeeBean.getCalculationDays());
            row.add(storageFeeBean.getWarehouseRent());
            row.add(storageFeeBean.getK3CategoryName());
            rows.add(row);
        }
        ExcelData excelData = new ExcelData();
        excelData.setRows(rows);
        excelData.setTitles(Arrays.asList(titles));
        return excelData;
    }

}
