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

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.clx.order.feign.OrderFeign;
import com.clx.order.vo.pc.owner.OwnerQuotationDetailVO;
import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.dao.OwnerAccountPasswordDao;
import com.clx.performance.dao.breakcontract.BreakContractOwnerRecordDao;
import com.clx.performance.dao.breakcontract.BreakContractOwnerRuleDao;
import com.clx.performance.dao.breakcontract.BreakContractSettlementLogDao;
import com.clx.performance.dao.breakcontract.BreakContractSettlementOwnerDao;
import com.clx.performance.dao.settle.SettlementPlatformAccountDao;
import com.clx.performance.enums.*;
import com.clx.performance.extranal.order.QuotationService;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.model.OwnerAccountPassword;
import com.clx.performance.model.breakcontract.BreakContractOwnerRecord;
import com.clx.performance.model.breakcontract.BreakContractOwnerRule;
import com.clx.performance.model.breakcontract.BreakContractSettlementLog;
import com.clx.performance.model.breakcontract.BreakContractSettlementOwner;
import com.clx.performance.model.settle.SettlementPlatformAccount;
import com.clx.performance.param.feign.OrderAdjustTonnageDownParam;
import com.clx.performance.param.pc.breakcontract.carrier.*;
import com.clx.performance.service.OwnerAccountService;
import com.clx.performance.service.breakcontract.BreakContractOwnerRecordService;
import com.clx.performance.service.breakcontract.BreakContractSettlementLogService;
import com.clx.performance.service.breakcontract.BreakContractSettlementOwnerService;
import com.clx.performance.struct.breakcontract.BreakContractSettlementLogStruct;
import com.clx.performance.struct.breakcontract.BreakContractSettlementOwnerStruct;
import com.clx.performance.utils.MyMD5Util;
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.BreakContractOwnerRuleVO;
import com.clx.performance.vo.pc.breakcontract.carrier.CarrierBreakContractSettlementLogVO;
import com.clx.performance.vo.pc.breakcontract.carrier.CarrierBreakContractSettlementOwnerDetailVO;
import com.clx.performance.vo.pc.breakcontract.carrier.PageCarrierBreakContractSettlementOwnerVO;
import com.clx.performance.vo.pc.owner.settle.SettlementPlatformAccountVO;
import com.clx.user.vo.pc.owner.OwnerBindCardVO;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.utils.LocalDateTimeUtils;
import com.msl.user.data.UserSessionData;
import com.msl.user.utils.TokenUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author liruixin
 * Date 2023-10-24
 * Time 16:02
 */
@Service
@Slf4j
@AllArgsConstructor
public class BreakContractSettlementOwnerServiceImpl  implements BreakContractSettlementOwnerService {

    private final BreakContractSettlementOwnerDao breakContractSettlementOwnerDao;
    private final BreakContractSettlementOwnerStruct breakContractSettlementOwnerStruct;
    private final BreakContractSettlementLogDao breakContractSettlementLogDao;
    private final BreakContractSettlementLogStruct breakContractSettlementLogStruct;
    private final BreakContractSettlementLogService breakContractSettlementLogService;
    private final OrderChildDao orderChildDao;
    private final BreakContractOwnerRuleDao breakContractOwnerRuleDao;
    private final SettlementPlatformAccountDao settlementPlatformAccountDao;
    private final OwnerAccountService ownerAccountService;
    private final OrderFeign orderFeign;
    private final QuotationService quotationService;
    private final BreakContractOwnerRecordService breakContractOwnerRecordService;
    private final BreakContractOwnerRecordDao breakContractOwnerRecordDao;
    private final OrderGoodsDao orderGoodsDao;
    private final OwnerAccountPasswordDao ownerAccountPasswordDao;


    

    @Override
    public IPage<PageCarrierBreakContractSettlementOwnerVO> pageCarrierBreakContractSettlementOwnerList(PageCarrierBreakContractSettlementOwnerParam param) {
        IPage<BreakContractSettlementOwner> breakContractSettlementDriverDetail = breakContractSettlementOwnerDao.pageCarrierBreakContractSettlementOwnerList(param);
        List<PageCarrierBreakContractSettlementOwnerVO> list = breakContractSettlementOwnerStruct.covertToCarrierList(breakContractSettlementDriverDetail.getRecords());
        return new Page<PageCarrierBreakContractSettlementOwnerVO>().setRecords(list).setTotal(breakContractSettlementDriverDetail.getTotal()).setPages(breakContractSettlementDriverDetail.getPages());

    }

    @Override
    public SXSSFWorkbook exportCarrierBreakContractSettlementOwnerList(PageCarrierBreakContractSettlementOwnerParam param) {
        param.setPage(1);
        param.setPageSize(1000000);
        IPage<PageCarrierBreakContractSettlementOwnerVO> settlementOwnerDetail = pageCarrierBreakContractSettlementOwnerList(param);

        List<PageCarrierBreakContractSettlementOwnerVO> list = settlementOwnerDetail.getRecords();

        // 组装表头
        List<ExcelField> fieldList = new ArrayList<>();
        fieldList.add(new ExcelField(0, "序号", "index", 2000));
        fieldList.add(new ExcelField(1, "结算单号", "settlementNo", 5000));
        fieldList.add(new ExcelField(2, "订单编号", "orderNo", 5000));
        fieldList.add(new ExcelField(3, "货主编号", "ownUserNo", 5000));
        fieldList.add(new ExcelField(4, "货主名称", "ownerName", 5000));

        fieldList.add(new ExcelField(5, "违约方", "breakContractPartyType", 5000));
        fieldList.add(new ExcelField(6, "违约金额", "figure", 5000));
        fieldList.add(new ExcelField(7, "状态", "statusMsg", 5000));
        fieldList.add(new ExcelField(8, "创建人", "createName", 5000));
        fieldList.add(new ExcelField(9, "创建时间", "createTime", 5000));



        // 组装数据
        List<List<ExcelData>> dataList = new ArrayList<>();
        for (int i=0; i<list.size(); i++){

            PageCarrierBreakContractSettlementOwnerVO dto = list.get(i);
            List<ExcelData> rowData = new ArrayList<>();

            rowData.add(new ExcelData(i+1));
            rowData.add(new ExcelData(dto.getSettlementNo()));
            rowData.add(new ExcelData(dto.getOrderNo()));
            rowData.add(new ExcelData(dto.getOwnerUserNo()+""));
            rowData.add(new ExcelData(dto.getOwnerName()));

            rowData.add(new ExcelData(dto.getBreakContractPartyTypeMsg()));
            rowData.add(new ExcelData(dto.getFigure().movePointLeft(2)));
            rowData.add(new ExcelData(dto.getStatusMsg()));
            rowData.add(new ExcelData(dto.getCreateName()));
            rowData.add(new ExcelData(dto.getCreateTime()));


            dataList.add(rowData);
        }

        ExcelSheet excelSheet = new ExcelSheet("货主违约结算单", "货主违约结算单", fieldList, dataList);

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

    @Override
    public CarrierBreakContractSettlementOwnerDetailVO getCarrierBreakContractSettlementOwnerDetail(String settlementNo) {
        //结算单详情
        BreakContractSettlementOwner settlementOwner =breakContractSettlementOwnerDao.getDetailBySettlementNo(settlementNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        CarrierBreakContractSettlementOwnerDetailVO detail = breakContractSettlementOwnerStruct.convertToDetail(settlementOwner);

        List<BreakContractSettlementLog> settlementLogs = breakContractSettlementLogDao.getSettlementLogs(settlementNo);

        List<CarrierBreakContractSettlementLogVO> settlementLogVOS = breakContractSettlementLogStruct.covertToCarrierList(settlementLogs);
        detail.setLogs(settlementLogVOS);
        return detail;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void uploadInvoiceImg(CarrierUploadInvoiceImgParam param) {

        BreakContractSettlementOwner settlementOwner = breakContractSettlementOwnerDao.getEntityByKey(param.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(settlementOwner.getStatus(), BreakContractSettlementOwnerEnum.Status.TO_BE_ACCOUNT.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.STATUS_CHANGED);
        }
        breakContractSettlementOwnerDao.uploadInvoiceImg(param.getId(),param.getInvoiceImg());

        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        //保存结算单日志----上传结算凭证
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.UPLOAD_SETTLEMENT.getCode(),BreakContractSettlementLogEnum.Type.UPLOAD_SETTLEMENT.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCancelSettlement(CarrierCancelSettlementParam param) {
        BreakContractSettlementOwner settlementOwner = breakContractSettlementOwnerDao.getEntityByKey(param.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(settlementOwner.getStatus(), BreakContractSettlementOwnerEnum.Status.TO_BE_ACCOUNT.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.STATUS_CHANGED);
        }

        breakContractSettlementOwnerDao.updateStatus(param.getId(),BreakContractSettlementOwnerEnum.Status.TO_BE_ACCOUNT.getCode(),BreakContractSettlementOwnerEnum.Status.CANCEL.getCode());

        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        //保存结算单日志----取消结算单
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.CANCEL.getCode(),BreakContractSettlementLogEnum.Type.CANCEL.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveCarrierBreakContractPayee(CarrierBreakContractSavePayeeParam param) {
        BreakContractSettlementOwner settlementOwner = breakContractSettlementOwnerDao.getEntityByKey(param.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(settlementOwner.getStatus(), BreakContractSettlementOwnerEnum.Status.PLATFORM_TO_PAYMENT.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.STATUS_CHANGED);
        }

        param.setStatus(BreakContractSettlementOwnerEnum.Status.OWNER_CONFIRMED_PLATFORM_PAYMENT.getCode());
        breakContractSettlementOwnerDao.saveCarrierBreakContractPayee(param);

        BreakContractOwnerRecord record = new BreakContractOwnerRecord();
        record.setSettlementNo(settlementOwner.getSettlementNo());
        record.setPayStatus(BreakContractOwnerRecordEnum.PayStatus.YES.getCode());
        record.setPayTime(LocalDateTime.now());
        breakContractOwnerRecordDao.uploadPayTime(record);

        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        //保存结算单日志----平台付款
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.PLATFORM_TO_PAYMENT.getCode(),BreakContractSettlementLogEnum.Type.PLATFORM_TO_PAYMENT.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateCarrierBreakContractPayeeConfirm(CarrierBreakPayeeConfirmParam param) {
        BreakContractSettlementOwner settlementOwner = breakContractSettlementOwnerDao.getEntityByKey(param.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(settlementOwner.getStatus(), BreakContractSettlementOwnerEnum.Status.PLATFORM_CONFIRMED_OWNER_PAYMENT.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.STATUS_CHANGED);
        }

        breakContractSettlementOwnerDao.updateStatus(param.getId(),BreakContractSettlementOwnerEnum.Status.PLATFORM_CONFIRMED_OWNER_PAYMENT.getCode(),BreakContractSettlementOwnerEnum.Status.COMPLETED.getCode());


        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        //保存结算单日志----平台确认付款
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.PLATFORM_CONFIRMED_OWNER_PAYMENT.getCode(),BreakContractSettlementLogEnum.Type.PLATFORM_CONFIRMED_OWNER_PAYMENT.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());

        //保存结算单日志----已完结
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.COMPLETED.getCode(),BreakContractSettlementLogEnum.Type.COMPLETED.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateConfirmSettlement(OwnerConfirmSettlementParam param) {
        BreakContractSettlementOwner settlementOwner = breakContractSettlementOwnerDao.getEntityByKey(param.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(settlementOwner.getStatus(), BreakContractSettlementOwnerEnum.Status.OWNER_TO_BE_CONFIRMED.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.STATUS_CHANGED);
        }

        int status = BreakContractSettlementOwnerEnum.Status.SHIPPER_TO_PAYMENT.getCode();
        if(Objects.equals(settlementOwner.getBreakContractPartyType(), BreakContractSettlementDriverEnum.BreakContractPartyType.PLATFORM.getCode())){
            status = BreakContractSettlementOwnerEnum.Status.PLATFORM_TO_PAYMENT.getCode();
        }
        breakContractSettlementOwnerDao.updateStatus(param.getId(),BreakContractSettlementOwnerEnum.Status.OWNER_TO_BE_CONFIRMED.getCode(),status);

        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        //保存结算单日志----确认结算单
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.OWNER_TO_BE_CONFIRMED.getCode(),BreakContractSettlementLogEnum.Type.OWNER_TO_BE_CONFIRMED.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveOwnerBreakContractPayee(CarrierBreakContractSavePayeeParam param) {
        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        if (StringUtils.equals(loginUserInfo.getProductCode(), "carrier-owner-app")) {
            OwnerAccountPassword entity = ownerAccountPasswordDao.findEntityByUserNo(loginUserInfo.getUserNo());
            try {
                boolean b = MyMD5Util.validPassword(param.getAccountPassword(), entity.getPassword());
                if (!b) {
                    throw new ServiceSystemException(PerformanceResultEnum.PASSWORD_CHECK_FAIL);
                }
            } catch (Exception e) {
                throw new ServiceSystemException(PerformanceResultEnum.PASSWORD_CHECK_FAIL);
            }
        }
        BreakContractSettlementOwner settlementOwner = breakContractSettlementOwnerDao.getEntityByKey(param.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(settlementOwner.getStatus(), BreakContractSettlementOwnerEnum.Status.SHIPPER_TO_PAYMENT.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.STATUS_CHANGED);
        }

        param.setStatus(BreakContractSettlementOwnerEnum.Status.PLATFORM_CONFIRMED_OWNER_PAYMENT.getCode());
        breakContractSettlementOwnerDao.saveCarrierBreakContractPayee(param);

        BreakContractOwnerRecord record = new BreakContractOwnerRecord();
        record.setSettlementNo(settlementOwner.getSettlementNo());
        record.setPayStatus(BreakContractOwnerRecordEnum.PayStatus.YES.getCode());
        record.setPayTime(LocalDateTime.now());
        breakContractOwnerRecordDao.uploadPayTime(record);

        //保存结算单日志----货主付款
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.SHIPPER_TO_PAYMENT.getCode(),BreakContractSettlementLogEnum.Type.SHIPPER_TO_PAYMENT.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateOwnerBreakContractPayeeConfirm(CarrierBreakPayeeConfirmParam param) {
        BreakContractSettlementOwner settlementOwner = breakContractSettlementOwnerDao.getEntityByKey(param.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(!Objects.equals(settlementOwner.getStatus(), BreakContractSettlementOwnerEnum.Status.OWNER_CONFIRMED_PLATFORM_PAYMENT.getCode())){
            throw new ServiceSystemException(PerformanceResultEnum.STATUS_CHANGED);
        }

        breakContractSettlementOwnerDao.updateStatus(param.getId(),BreakContractSettlementOwnerEnum.Status.OWNER_CONFIRMED_PLATFORM_PAYMENT.getCode(),BreakContractSettlementOwnerEnum.Status.COMPLETED.getCode());


        UserSessionData loginUserInfo = TokenUtil.getLoginUserInfo();
        //保存结算单日志----货主确认付款
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.OWNER_CONFIRMED_PLATFORM_PAYMENT.getCode(),BreakContractSettlementLogEnum.Type.OWNER_CONFIRMED_PLATFORM_PAYMENT.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());

        //保存结算单日志----已完结
        breakContractSettlementLogService.saveBreakSettlementLog(settlementOwner.getSettlementNo(),
                BreakContractSettlementLogEnum.Type.COMPLETED.getCode(),BreakContractSettlementLogEnum.Type.COMPLETED.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),loginUserInfo.getUserNo(),loginUserInfo.getUserName());
    }

    @Override
    public void saveSettlementOwnerForTonnageDown(OrderAdjustTonnageDownParam param) {
        //下调货物吨数
        if(param.getWeight().compareTo(BigDecimal.ZERO) <=0){
            return ;
        }

        //违约金方案
        BreakContractOwnerRule ownerRule = breakContractOwnerRuleDao.getEntityByKey(param.getLiquidatedDamagesPlanId())
                .orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(Objects.equals(ownerRule.getStatus(),2)){
            throw new ServiceSystemException(PerformanceResultEnum.BREAK_CONTRACT_RULE_NO_FOUND);
        }
        String autoRuleJson = ownerRule.getAutoRuleJson();//系统自动违规
        BreakContractOwnerRuleVO.AutoRule autoRule = JSONObject.parseObject(autoRuleJson, BreakContractOwnerRuleVO.AutoRule.class);
        BreakContractOwnerRuleVO.OrderAmountReduceRule reduceRule = autoRule.getOrderAmountReduceRule();//订单吨数减少规则

        //运单状态（不包括取消）
        List<Integer> breakStatusList = getBreakStatusList();

        BigDecimal figure ;//总费用

        //订单号查询货单
        List<OrderGoods> orderGoods = orderGoodsDao.getOrderGoodsListByOrderNo(param.getOrderNo());

        if(CollectionUtils.isEmpty(orderGoods)){
            BigDecimal totalFreight = param.getTransportWeight().multiply(param.getValidFreightPrice());
            figure = totalFreight.multiply(reduceRule.getBeforeRatio()).multiply(param.getWeight())
                    .divide(param.getTransportWeight(),2, BigDecimal.ROUND_HALF_UP);
        }else{

            List<OrderChild> orderChilds = orderChildDao.listOrderChildByOrderNoAndStatus(param.getOrderNo(), breakStatusList);

            if(CollectionUtils.isEmpty(orderChilds)){
                BigDecimal totalFreight = param.getTransportWeight().multiply(param.getValidFreightPrice());
                figure = totalFreight.multiply(reduceRule.getAfterRatio()).multiply(param.getWeight())
                        .divide(param.getTransportWeight(),2, BigDecimal.ROUND_HALF_UP);
            }else{

                BigDecimal deliveredWeight = BigDecimal.ZERO;//已拉运的重量
                BigDecimal deliveredFreight = BigDecimal.ZERO;//已拉运的费用
                for(OrderChild orderChild : orderChilds){
                    if(orderChild.getLoadNet() == null){
                        deliveredWeight = deliveredWeight.add(orderChild.getWeight()) ;
                        deliveredFreight = deliveredFreight.add(orderChild.getOrderFreightPrice().multiply(orderChild.getWeight()));
                    }else{
                        deliveredWeight = deliveredWeight.add(orderChild.getLoadNet()) ;
                        deliveredFreight = deliveredFreight.add(orderChild.getOrderFreightPrice().multiply(orderChild.getLoadNet()));
                    }

                }
                BigDecimal noTransitWeight = param.getTransportWeight().subtract(deliveredWeight);//未拉运的重量
                BigDecimal noTransitFreight = noTransitWeight.multiply(param.getValidFreightPrice());//未拉运的费用
                BigDecimal totalFreight = deliveredFreight.add(noTransitFreight);
                figure = totalFreight.multiply(reduceRule.getAfterRatio()).multiply(param.getWeight())
                        .divide(param.getTransportWeight(),2, BigDecimal.ROUND_HALF_UP);
            }
        }

        //组装参数 生成违约记录 违约计费  违约结算单
        BreakContractOwnerRecordAddParam ownerRecordAddParam = new BreakContractOwnerRecordAddParam();
        ownerRecordAddParam.setBreakContractPartyType(BreakContractRecordEnum.BreakContractPartyType.OWNER.getCode());
        ownerRecordAddParam.setFigure(figure);
        ownerRecordAddParam.setOrderNo(param.getOrderNo());
        ownerRecordAddParam.setRemark("下调吨数产生违约");
        breakContractOwnerRecordService.autoSaveRecord(ownerRecordAddParam);

    }

    @Override
    public SettlementPlatformAccountVO getCarrierSettlementPlatformAccount(Integer id) {
        //平台账号
        SettlementPlatformAccount platformAccount = settlementPlatformAccountDao.getSettlementPlatformAccount();
        //返回对象
        SettlementPlatformAccountVO vo = new SettlementPlatformAccountVO();
        if(Objects.nonNull(platformAccount)){
            vo.setPaymentBankCardNo(platformAccount.getBankCardNo());
            vo.setPaymentBankName(platformAccount.getBankName());
        }
        //货主账号
        BreakContractSettlementOwner settlementOwner = breakContractSettlementOwnerDao.getEntityByKey(id).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        OwnerBindCardVO card = ownerAccountService.getOwnerBindCard(settlementOwner.getOwnerUserNo());
        if(Objects.nonNull(card)){
            vo.setPayee(card.getName());
            vo.setPayeeBankName(card.getOwnerAccountBank());
            vo.setPayeeBankCardNo(card.getOwnerBankAccount());
        }
        return vo;
    }

    @Override
    public void saveSettlementOwnerForCancelOrder(BigDecimal transportWeight,BigDecimal validFreightPrice,String orderNo,Integer cancelType) {

        //获取订单配置的违约金方案
        OwnerQuotationDetailVO quotationDetailVO = quotationService.getQuotationByOrderNo(orderNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(Objects.isNull(quotationDetailVO.getLiquidatedDamagesPlanId())){
            throw new ServiceSystemException(PerformanceResultEnum.DATA_NOT_FIND);
        }

        //获取违约金方案详情
        BreakContractOwnerRule ownerRule = breakContractOwnerRuleDao.getEntityByKey(quotationDetailVO.getLiquidatedDamagesPlanId())
                .orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if(Objects.equals(ownerRule.getStatus(),2)){
            throw new ServiceSystemException(PerformanceResultEnum.BREAK_CONTRACT_RULE_NO_FOUND);
        }

        String autoRuleJson = ownerRule.getAutoRuleJson();//系统自动违规
        BreakContractOwnerRuleVO.AutoRule autoRule = JSONObject.parseObject(autoRuleJson, BreakContractOwnerRuleVO.AutoRule.class);
        BreakContractOwnerRuleVO.OrderCancelRule orderCancelRule = autoRule.getOrderCancelRule();//订单取消规则

        List<Integer> breakStatusList = getBreakStatusList();

        //由于已经更新了订单状态为货主取消了
        if(Objects.equals(cancelType,CancelOrderEnum.Type.NOT_ARRIVE.getCode())){
            breakStatusList.add(OrderChildEnum.Status.OWNER_CANCEL.getCode());
        }

        BigDecimal figure ;//总费用

        //订单号查询货单
        List<OrderGoods> orderGoods = orderGoodsDao.getOrderGoodsListByOrderNo(orderNo);

        if(CollectionUtils.isEmpty(orderGoods)){
            figure = transportWeight.multiply(validFreightPrice).multiply(orderCancelRule.getBeforeRatio());
        }else{

            List<OrderChild> orderChilds = orderChildDao.listOrderChildByOrderNoAndStatus(orderNo, breakStatusList);

            //没有司机拉运
            if(CollectionUtils.isEmpty(orderChilds)){
                figure = transportWeight.multiply(validFreightPrice).multiply(orderCancelRule.getAfterRatio());
            }else{
                BigDecimal deliveredWeight = BigDecimal.ZERO;//已拉运的重量
                BigDecimal cancelWeight = BigDecimal.ZERO;//可取消的重量
                BigDecimal deliveredFreight = BigDecimal.ZERO;//已拉运的费用
                BigDecimal seconds = BigDecimal.ZERO;//总毫秒数
                for(OrderChild orderChild : orderChilds){
                    if(orderChild.getLoadNet() == null){
                        deliveredWeight = deliveredWeight.add(orderChild.getWeight()) ;
                        deliveredFreight = deliveredFreight.add(orderChild.getOrderFreightPrice().multiply(orderChild.getWeight()));
                    }else{
                        deliveredWeight = deliveredWeight.add(orderChild.getLoadNet()) ;
                        deliveredFreight = deliveredFreight.add(orderChild.getOrderFreightPrice().multiply(orderChild.getLoadNet()));
                    }

                    if(Objects.equals(cancelType,CancelOrderEnum.Type.NOT_ARRIVE.getCode())){
                        if(Objects.equals(orderChild.getStatus(),OrderChildEnum.Status.OWNER_CANCEL.getCode())) {
                            cancelWeight = cancelWeight.add(orderChild.getWeight());
                            seconds = seconds.add(new BigDecimal(LocalDateTimeUtils.getSecondsDiff(orderChild.getPayTime(),orderChild.getCancelTime())));
                        }
                    }else{
                        if(Objects.equals(orderChild.getStatus(),OrderChildEnum.Status.CREATED.getCode())
                                || Objects.equals(orderChild.getStatus(),OrderChildEnum.Status.PAY.getCode())
                                || Objects.equals(orderChild.getStatus(),OrderChildEnum.Status.GO_TO_SEND.getCode())) {
                            cancelWeight = cancelWeight.add(orderChild.getWeight());
                        }
                    }

                }
                BigDecimal noTransitWeight = transportWeight.subtract(deliveredWeight);//未拉运的重量
                BigDecimal noTransitFreight = noTransitWeight.multiply(validFreightPrice);//未拉运的费用
                BigDecimal totalFreight = deliveredFreight.add(noTransitFreight);//总运费
                BigDecimal baseFigure;
                if(cancelWeight.compareTo(BigDecimal.ZERO) == 0){//没有取消的吨数
                    baseFigure = totalFreight.multiply(orderCancelRule.getAfterRatio());//基础违约金
                }else{
                    baseFigure = totalFreight.multiply(orderCancelRule.getAfterRatio()).multiply(cancelWeight)
                            .divide(transportWeight,2, BigDecimal.ROUND_HALF_UP);//基础违约金
                }

                //挂单后，车辆违约金
                BigDecimal truckFigure = BigDecimal.ZERO;
                if(Objects.equals(cancelType,CancelOrderEnum.Type.NOT_ARRIVE.getCode())){
                    truckFigure = seconds.multiply(orderCancelRule.getAfterFigurePerHour())
                            .divide(new BigDecimal(3600),2, BigDecimal.ROUND_HALF_UP).movePointRight(2);
                }

                figure = baseFigure.add(truckFigure);
            }
        }


        //组装参数 生成违约记录 违约计费  违约结算单
        BreakContractOwnerRecordAddParam ownerRecordAddParam = new BreakContractOwnerRecordAddParam();
        ownerRecordAddParam.setBreakContractPartyType(BreakContractRecordEnum.BreakContractPartyType.OWNER.getCode());
        ownerRecordAddParam.setFigure(figure);
        ownerRecordAddParam.setOrderNo(orderNo);
        ownerRecordAddParam.setRemark("订单取消产生违约");
        breakContractOwnerRecordService.autoSaveRecord(ownerRecordAddParam);
    }


    /**
     * 违约订单状态
     * @return
     */
    private  List<Integer> getBreakStatusList(){
        //运单状态
        List<Integer> statusList = new ArrayList<>();
        statusList.add(OrderChildEnum.Status.CREATED.getCode());
        statusList.add(OrderChildEnum.Status.PAY.getCode());
        statusList.add(OrderChildEnum.Status.GO_TO_SEND.getCode());
        statusList.add(OrderChildEnum.Status.ARRIVE_SEND.getCode());
        statusList.add(OrderChildEnum.Status.LOAD.getCode());
        statusList.add(OrderChildEnum.Status.GO_TO_RECEIVE.getCode());
        statusList.add(OrderChildEnum.Status.ARRIVE_RECEIVE.getCode());
        statusList.add(OrderChildEnum.Status.UNLOAD.getCode());
        statusList.add(OrderChildEnum.Status.UNSETTLE.getCode());
        statusList.add(OrderChildEnum.Status.COMPLETE.getCode());
        return statusList;

    }
}
