package com.clx.performance.service.impl.settle;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.clx.order.enums.InvoicingCompanyEnum;
import com.clx.order.vo.pc.carrier.InvoicingCompanyVO;
import com.clx.performance.dao.settle.SettlementDriverDetailDao;
import com.clx.performance.enums.PerformanceResultEnum;
import com.clx.performance.enums.loan.OwnerLoanRecordEnum;
import com.clx.performance.enums.settle.SettlementDriverEnum;
import com.clx.performance.enums.settle.SettlementOwnerEnum;
import com.clx.performance.extranal.order.InvoicingCompanyService;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.settle.SettlementDriverDetail;
import com.clx.performance.param.pc.breakcontract.carrier.PageCarrierBreakContractSettlementDriverDetailParam;
import com.clx.performance.param.pc.driver.PageCarrierSettlementDriverDetailParam;
import com.clx.performance.service.settle.SettlementDriverDetailService;
import com.clx.performance.struct.settle.SettlementDriverDetailStruct;
import com.clx.performance.utils.excel.ExcelData;
import com.clx.performance.utils.excel.ExcelField;
import com.clx.performance.utils.excel.ExcelSheet;
import com.clx.performance.utils.excel.ExcelUtil;
import com.clx.performance.vo.pc.breakcontract.carrier.PageCarrierBreakContractSettlementDriverDetailVO;
import com.clx.performance.vo.pc.carrier.settle.CarrierPageSettlementDriverDetailVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author liruixin
 * Date 2023-10-12
 * Time 09:43
 */
@Service
@Slf4j
@AllArgsConstructor
public class SettlementDriverDetailServiceImpl  implements SettlementDriverDetailService {

    private final SettlementDriverDetailDao settlementDriverDetailDao;
    private final SettlementDriverDetailStruct settlementOwnerDetailStruct;
    private final InvoicingCompanyService invoicingCompanyService;

    @Override
    public SettlementDriverDetail saveSettlementDetail(OrderChild orderChild) {

        SettlementDriverDetail settlementDriverDetail = new SettlementDriverDetail();
        settlementDriverDetail.setChildNo(orderChild.getChildNo());
        settlementDriverDetail.setOrderGoodsNo(orderChild.getOrderGoodsNo());
        settlementDriverDetail.setOrderNo(orderChild.getOrderNo());

        settlementDriverDetail.setDriverUserNo(orderChild.getTruckOwnUserNo());
        settlementDriverDetail.setDriverName(orderChild.getTruckOwnName());
        settlementDriverDetail.setTruckNo(orderChild.getTruckNo());

        settlementDriverDetail.setGoodsId(orderChild.getGoodsId());
        settlementDriverDetail.setGoodsName(orderChild.getGoodsName());

        // 运费
        settlementDriverDetail.setFreightPrice(orderChild.getFreightPrice());     //平台运费
        settlementDriverDetail.setWeight(weightCalc(orderChild.getLoadNet(), orderChild.getUnloadNet()));
        settlementDriverDetail.setFreight(freightCalc(settlementDriverDetail.getFreightPrice(), settlementDriverDetail.getWeight()));

        // 亏吨
        settlementDriverDetail.setLossPrice(orderChild.getLossPrice());
        settlementDriverDetail.setLossWeight(lossWeightCalc(orderChild.getLoadNet(), orderChild.getUnloadNet()));
        settlementDriverDetail.setLossFreight(lossFreightCalc(settlementDriverDetail.getLossPrice(), settlementDriverDetail.getLossWeight()));

        // 预付运费
        settlementDriverDetail.setPrepayFreight(BigDecimal.ZERO);

        // 结算金额
        settlementDriverDetail.setSettlementFreight(settlementFreightCalc(settlementDriverDetail.getFreight(), settlementDriverDetail.getLossFreight()));

        // 平台服务费： 司机结算金额*平台服务费费率
        settlementDriverDetail.setPlatformServiceFeeRate(orderChild.getPlatformServiceFeeRate()==null
                ? BigDecimal.ZERO
                : orderChild.getPlatformServiceFeeRate());
        settlementDriverDetail.setPlatformServiceFee(orderChild.getPlatformServiceFee()==null
                ? BigDecimal.ZERO
                : orderChild.getPlatformServiceFee());

        // 开票配置
        Integer invoiceConfigType = invoicingCompanyService.getInvoicingConfigTypeByOrderNo(orderChild.getOrderNo());
        settlementDriverDetail.setInvoiceConfigType(invoiceConfigType);
        // 若开票配置为否，设置开票标识为普通单
        if (Objects.nonNull(invoiceConfigType) && Objects.equals(invoiceConfigType, InvoicingCompanyEnum.YesAndNo.NO.getCode())) {
            // 开票标识
            settlementDriverDetail.setInvoiceType(InvoicingCompanyEnum.RiskProcessType.AUTO.getCode());
        } else if (Objects.nonNull(invoiceConfigType) && Objects.equals(invoiceConfigType, InvoicingCompanyEnum.YesAndNo.YES.getCode())) {
            //设置开票公司信息
            settlementDriverDetail.setInvoicingCompanyId(orderChild.getInvoicingCompanyId());
            settlementDriverDetail.setInvoicingCompanyShorterName(orderChild.getInvoicingCompanyShorterName());
            settlementDriverDetail.setInvoicingCompanyGroupCode(orderChild.getInvoicingCompanyGroupCode());
        }

        settlementDriverDetailDao.saveEntity(settlementDriverDetail);

        return settlementDriverDetail;
    }

    private BigDecimal weightCalc(BigDecimal loadNet, BigDecimal unLoadNet){
        return unLoadNet.compareTo(loadNet) < 0? unLoadNet : loadNet;
    }

    /**
     *  运费计算
     */
    public BigDecimal freightCalc(BigDecimal freightPrice, BigDecimal weight){

        return freightPrice.multiply(weight).setScale(0, RoundingMode.HALF_UP);
    }

    /**
     * 亏吨计算
     */
    private BigDecimal lossWeightCalc(BigDecimal loadNet, BigDecimal unLoadNet){
        return unLoadNet.compareTo(loadNet) < 0? loadNet.subtract(unLoadNet) : BigDecimal.ZERO;
    }

    /**
     * 亏吨运费
     */
    private BigDecimal lossFreightCalc(BigDecimal freightPrice, BigDecimal weight){
        return freightPrice.multiply(weight).setScale(0, RoundingMode.HALF_UP);

    }

    /**
     * 结算金额
     */
    private BigDecimal settlementFreightCalc(BigDecimal freight, BigDecimal lossFreight){
        return freight.subtract(lossFreight);
    }

    @Override
    public IPage<CarrierPageSettlementDriverDetailVO> pageSettlementDriverDetail(
            PageCarrierSettlementDriverDetailParam param) {
        IPage<SettlementDriverDetail> result = settlementDriverDetailDao.pageSettlementDriverDetail(param);
        List<CarrierPageSettlementDriverDetailVO> list = settlementOwnerDetailStruct.covertList(result.getRecords());
        return new Page<CarrierPageSettlementDriverDetailVO>().setRecords(list).setTotal(result.getTotal()).setPages(result.getPages());
    }

    @Override
    public SettlementDriverDetail selectOneByChildNo(String childNo) {
        return settlementDriverDetailDao.getByChildNo(childNo).get();
    }

    @Override
    public SXSSFWorkbook exportSettlementDriverDetail(PageCarrierSettlementDriverDetailParam param) {
        param.setPage(1);
        param.setPageSize(1000000);
        IPage<CarrierPageSettlementDriverDetailVO> settlementDriverDetailPage = pageSettlementDriverDetail(param);

        List<CarrierPageSettlementDriverDetailVO> list = settlementDriverDetailPage.getRecords();

        // 组装表头
        List<ExcelField> fieldList = new ArrayList<>();
        fieldList.add(new ExcelField(0, "运单编号", "childNo", 5000));
        fieldList.add(new ExcelField(1, "货单编号", "orderGoodsNo", 5000));
        fieldList.add(new ExcelField(2, "订单编号", "orderNo", 5000));
        fieldList.add(new ExcelField(3, "车主编码", "driverUserNo", 5000));
        fieldList.add(new ExcelField(4, "车主名称", "driverName", 5000));
        fieldList.add(new ExcelField(5, "货物名称", "goodsName", 5000));
        fieldList.add(new ExcelField(6, "车牌号", "truckNo", 5000));
        fieldList.add(new ExcelField(7, "开票配置", "invoicingConfigType", 5000));
        fieldList.add(new ExcelField(8, "开票公司", "invoicingCompanyShorterName", 5000));
        fieldList.add(new ExcelField(9, "开票标识", "invoiceType", 5000));
        fieldList.add(new ExcelField(10, "借款标识", "loanFlagMsg", 5000));
        fieldList.add(new ExcelField(11, "预付标识", "prepayFreightFlag", 5000));
        fieldList.add(new ExcelField(12, "实际净重（吨）", "weight", 5000));
        fieldList.add(new ExcelField(13, "运费单价", "freightPrice", 5000));
        fieldList.add(new ExcelField(14, "应付运费", "freight", 5000));
        fieldList.add(new ExcelField(15, "货损单价", "lossPrice", 5000));
        fieldList.add(new ExcelField(16, "货损吨数", "lossWeight", 5000));
        fieldList.add(new ExcelField(17, "货损金额", "lossFreight", 5000));
        fieldList.add(new ExcelField(18, "结算金额", "settlementFreight", 5000));
        fieldList.add(new ExcelField(19, "毛利率", "platformServiceFeeRate", 5000));
        fieldList.add(new ExcelField(20, "毛利润", "platformServiceFee", 5000));
        fieldList.add(new ExcelField(21, "结算单号", "settlementNo", 5000));
        fieldList.add(new ExcelField(22, "创建时间", "createTime", 5000));

        // 组装数据
        List<List<ExcelData>> dataList = new ArrayList<>();
        for (CarrierPageSettlementDriverDetailVO dto : list) {

            List<ExcelData> rowData = new ArrayList<>();

            rowData.add(new ExcelData(dto.getChildNo()));
            rowData.add(new ExcelData(dto.getOrderGoodsNo()));
            rowData.add(new ExcelData(dto.getOrderNo()));
            rowData.add(new ExcelData(dto.getDriverUserNo() + ""));


            rowData.add(new ExcelData(dto.getDriverName()));
            rowData.add(new ExcelData(dto.getGoodsName()));
            rowData.add(new ExcelData(dto.getTruckNo()));
            // 开票配置
            rowData.add(new ExcelData(dto.getInvoiceConfigType()==null?null:SettlementOwnerEnum.InvoiceConfigType.getMsgByCode(dto.getInvoiceConfigType())));
            rowData.add(new ExcelData(dto.getInvoicingCompanyShorterName()));
            rowData.add(new ExcelData(dto.getInvoiceType()==null?null:SettlementOwnerEnum.InvoiceType.getMsgByCode(dto.getInvoiceType())));
            rowData.add(new ExcelData(dto.getPrepayFreightFlag()==null?null:SettlementDriverEnum.PrepayFreightFlag.getMsgByCode(dto.getPrepayFreightFlag())));
            rowData.add(new ExcelData(dto.getLoanFlagMsg()));
            rowData.add(new ExcelData(dto.getWeight()));
            rowData.add(new ExcelData(dto.getFreightPrice()==null?null:dto.getFreightPrice().movePointLeft(2)));
            rowData.add(new ExcelData(dto.getFreight()==null?null:dto.getFreight().movePointLeft(2)));
            rowData.add(new ExcelData(dto.getLossPrice()==null?null:dto.getLossPrice().movePointLeft(2)));
            rowData.add(new ExcelData(dto.getLossWeight()));
            rowData.add(new ExcelData(dto.getLossFreight()==null?null:dto.getLossFreight().movePointLeft(2)));
            rowData.add(new ExcelData(dto.getSettlementFreight()==null?null:dto.getSettlementFreight().movePointLeft(2)));
            rowData.add(new ExcelData(dto.getPlatformServiceFeeRate() + "%"));
            rowData.add(new ExcelData(dto.getPlatformServiceFee()==null?null:dto.getPlatformServiceFee().movePointLeft(2)));
            rowData.add(new ExcelData(dto.getSettlementNo()));
            rowData.add(new ExcelData(dto.getCreateTime()));

            dataList.add(rowData);
        }

        ExcelSheet excelSheet = new ExcelSheet("车主运单计费", "车主运单计费", fieldList, dataList);

        //创建excel
        return ExcelUtil.create(excelSheet);
    }

    public static String formatLoanMsg(Integer loanFlag) {
        if (Objects.equals(loanFlag, OwnerLoanRecordEnum.LoanFlag.LOAN.getCode())) {
            return OwnerLoanRecordEnum.LoanFlag.LOAN.getMsg();
        }else if (Objects.equals(loanFlag, OwnerLoanRecordEnum.LoanFlag.NO_LOAN.getCode())) {
            return OwnerLoanRecordEnum.LoanFlag.NO_LOAN.getMsg();
        } else if (Objects.equals(loanFlag, OwnerLoanRecordEnum.LoanFlag.RE_PAY.getCode())) {
            return OwnerLoanRecordEnum.LoanFlag.RE_PAY.getMsg();
        }
        return "无需借款";
    }
}
