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

import cn.hutool.json.JSONUtil;
import com.clx.order.enums.InvoicingCompanyEnum;
import com.clx.order.enums.QuotationEnum;
import com.clx.order.vo.feign.FeignOrderInfoVO;
import com.clx.order.vo.pc.carrier.InvoicingCompanyVO;
import com.clx.performance.config.MslPaymentConfig;
import com.clx.performance.constant.RedissonConstants;
import com.clx.performance.dao.OrderChildDao;
import com.clx.performance.dao.OrderChildSyncTransportInvoiceRecordDao;
import com.clx.performance.dao.OrderGoodsDao;
import com.clx.performance.dao.settle.SettlementOrderChildRiskDao;
import com.clx.performance.dao.settle.*;
import com.clx.performance.dto.InvoicingStatusNotifyDTO;
import com.clx.performance.dto.PayStatusNotifyDTO;
import com.clx.performance.enums.*;
import com.clx.performance.enums.settle.SettlementOrderChildRiskEnum;
import com.clx.performance.enums.settle.*;
import com.clx.performance.event.OwnerLoanThawEvent;
import com.clx.performance.extranal.broker.BrokerService;
import com.clx.performance.extranal.order.InvoicingCompanyService;
import com.clx.performance.extranal.user.DriverService;
import com.clx.performance.extranal.user.OrderService;
import com.clx.performance.extranal.user.OwnerInfoService;
import com.clx.performance.listener.OrderChildSyncTransportListener;
import com.clx.performance.model.OrderChild;
import com.clx.performance.model.OrderGoods;
import com.clx.performance.model.settle.SettlementOrderChildRisk;
import com.clx.performance.model.settle.*;
import com.clx.performance.param.pc.payment.PayParam;
import com.clx.performance.param.pc.payment.PayPlatformFeeParam;
import com.clx.performance.service.OrderChildLogService;
import com.clx.performance.service.PaymentService;
import com.clx.performance.service.broker.OrderChildBrokerMqService;
import com.clx.performance.service.broker.OrderChildBrokerService;
import com.clx.performance.service.impl.UniqueOrderNumService;
import com.clx.performance.service.settle.*;
import com.clx.performance.utils.LocalDateTimeUtils;
import com.clx.performance.utils.RedisUtil;
import com.clx.performance.utils.spring.ApplicationContextUtils;
import com.clx.performance.vo.mq.*;
import com.clx.performance.vo.mq.settle.*;
import com.clx.performance.vo.pc.broker.TransportVO;
import com.clx.user.vo.feign.DriverInfoFeignVo;
import com.clx.user.vo.feign.OwnerInfoFeignVO;
import com.msl.common.enums.ResultCodeEnum;
import com.msl.common.exception.ServiceSystemException;
import com.msl.common.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SettlementMqHandlerServiceImpl implements SettlementMqHandlerService {

    @Autowired
    private SettlementOwnerDetailDao settlementOwnerDetailDao;
    @Autowired
    private SettlementDriverDetailDao settlementDriverDetailDao;
    @Autowired
    private SettlementOwnerDao settlementOwnerDao;
    @Autowired
    private SettlementDriverDao settlementDriverDao;

    @Autowired
    private OwnerInfoService ownerInfoService;

    @Autowired
    private UniqueOrderNumService uniqueOrderNumService;

    @Autowired
    private SettlementService settlementService;

    @Autowired
    private  SettlementLogService settlementLogService;

    @Autowired
    private DriverService driverService;

    @Autowired
    private PaymentService paymentService;


    @Autowired
    private OrderGoodsDao orderGoodsDao;

    @Autowired
    private MslPaymentConfig mslPaymentConfig;

    @Autowired
    private OrderChildDao orderChildDao;

    @Autowired
    private SettlementPlatformServiceFeeDao settlementPlatformServiceFeeDao;

    @Autowired
    private OrderChildSyncTransportInvoiceRecordDao orderChildSyncTransportInvoiceRecordDao;

    @Autowired
    private OrderChildLogService orderChildLogService;

    @Autowired
    RedisUtil redisUtil;

    @Autowired
    private OrderChildSyncTransportRecordService childSyncTransportRecordService;

    @Autowired
    private OrderService orderService;

    @Autowired
    private OrderChildSyncTransportListener orderChildSyncTransportListener;

    @Autowired
    private BrokerService brokerService;

    @Autowired
    private OrderChildSyncTransportRecordService orderChildSyncTransportRecordService;

    @Autowired
    private SettlementMqService settlementMqService;

    @Autowired
    private OrderChildSyncTransportRecordDao orderChildSyncTransportRecordDao;

    @Autowired
    private SettlementOrderChildRiskDao settlementOrderChildRiskDao;

    @Autowired
    private OrderChildBrokerService orderChildBrokerService;

    @Autowired
    private InvoicingCompanyService invoicingCompanyService;

    @Autowired
    private SettlementCommonService settlementCommonService;

    @Autowired
    private ApplicationEventPublisher applicationEventPublisher;

    @Autowired
    private OrderChildBrokerMqService orderChildBrokerMqService;

    @Autowired
    private NetworkDriverRunningWaterRecordService networkDriverRunningWaterRecordService;

    @Autowired
    private SettlementPostService settlementPostService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void settlementStatistics(SettlementStatisticsMqParam mq) {
        OrderChild orderChild = orderChildDao
                .getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
        OrderGoods orderGoods = orderGoodsDao
                .getByOrderGoodsNo(orderChild.getOrderGoodsNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao
                .getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        // 拆单
        if (Objects.equals(mq.getType(), SettlementStatisticsMqParam.Type.SEPARATE.getCode())){
            settlementStatisticsSeparate(settlementOwnerDetail);

            // 发送mq (运单更新)
            orderChildBrokerMqService.orderChildUpdate(settlementOwnerDetail.getChildNo());

            return;
        }

        if (settlementOwnerDetail.getInvoiceFreight() == null) {
            log.info("当前车主计费信息开票金额为空,需要重新处理计算开票金额");
            settlementOwnerDetail.setInvoiceFreight(invoiceFreightCalc(orderChild.getSettlementWay(), orderGoods.getInvoiceServiceFeeRate(), settlementOwnerDetail));
            SettlementOwnerDetail update = new SettlementOwnerDetail();
            update.setId(settlementOwnerDetail.getId());
            update.setInvoiceFreight(settlementOwnerDetail.getInvoiceFreight());
            settlementOwnerDetailDao.updateEntityByKey(update);
        }
        String settlementNo = null ;
        SettlementOwner settlementOwner = null;

        OwnerInfoFeignVO ownerInfo = ownerInfoService.getOwnerInfo(settlementOwnerDetail.getOwnerUserNo());

        if (Objects.equals(orderGoods.getSettlementAccountPeriod(),2)){  //月结
            log.info("月结初始化货主结算单");
            LocalDateTime settlementPeriodTime = LocalDateTimeUtils.getBeginMonthDate();
            settlementOwner = settlementOwnerDao.selectUnlockOfSettlementPeriodMonth(settlementOwnerDetail.getOrderNo(),
                    settlementOwnerDetail.getInvoicingCompanyId(),
                    settlementPeriodTime, settlementOwnerDetail.getInvoiceType()).orNull();
            if (settlementOwner == null){   // 月结初始化
                settlementNo = settlementPeriodMonthInit(settlementOwnerDetail, settlementPeriodTime,
                        SettlementOwnerEnum.SettlementPeriodType.MONTH.getCode(), ownerInfo);
            }
            else {  // 月结更新
                settlementPeriodMonthUpdate(settlementOwner, settlementOwnerDetail);
                settlementNo = settlementOwner.getSettlementNo();
            }
        }
        else if (Objects.equals(orderGoods.getSettlementAccountPeriod(),
                SettlementOwnerEnum.SettlementPeriodType.DAILY.getCode())){  //日结
            log.info("日结初始化货主结算单");
            LocalDateTime settlementPeriodTime = LocalDateTimeUtils.getDayStart();
            settlementOwner = settlementOwnerDao.selectUnlockOfSettlementPeriodDaily(settlementOwnerDetail.getOrderNo(),
                    settlementOwnerDetail.getInvoicingCompanyId(),
                    settlementPeriodTime, settlementOwnerDetail.getInvoiceType()).orNull();
            if (settlementOwner == null){   // 日结初始化
                settlementNo = settlementPeriodMonthInit(settlementOwnerDetail, settlementPeriodTime,
                        SettlementOwnerEnum.SettlementPeriodType.DAILY.getCode(), ownerInfo);
            }
            else {  // 日结更新
                settlementPeriodMonthUpdate(settlementOwner, settlementOwnerDetail);
                settlementNo = settlementOwner.getSettlementNo();
            }
        }
        else {
            log.info("拉运完成结初始化货主结算单");

            settlementOwner = settlementOwnerDao.selectUnlockOfSettlementPeriodImmediate(settlementOwnerDetail.getOrderNo(),
                    settlementOwnerDetail.getInvoicingCompanyId(),
                    settlementOwnerDetail.getInvoiceType()).orNull();
            if (settlementOwner == null){   // 拉运完成初始化
                settlementNo = settlementPeriodMonthInit(settlementOwnerDetail, null,
                        SettlementOwnerEnum.SettlementPeriodType.IMMEDIATE.getCode(),ownerInfo);
            }
            else {  // 拉运完成更新
                settlementPeriodMonthUpdate(settlementOwner, settlementOwnerDetail);
                settlementNo = settlementOwner.getSettlementNo();
            }
        }

        // 更新结算单
        settlementOwnerDetail.setSettlementNo(settlementNo);
        settlementOwnerDetailDao.updateSettlementNo(settlementOwnerDetail);

        // 发送mq (运单更新)
        orderChildBrokerMqService.orderChildUpdate(settlementOwnerDetail.getChildNo());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void settlementDriverSettlement(SettlementDriverSettleMqParam mq) {

        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao
                .getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        SettlementDriver settlementDriver = settlementDriverDao.findByChildNo(settlementDriverDetail.getChildNo()).orNull();
        if (settlementDriver != null) {return;}

        String settlementNo = settlementNoGenerate();

        settlementDriver = new SettlementDriver();
        settlementDriver.setDriverUserNo(settlementDriverDetail.getDriverUserNo());
        settlementDriver.setDriverName(settlementDriverDetail.getDriverName());
        settlementDriver.setSettlementNo(settlementNo);
        settlementDriver.setChildNo(settlementDriverDetail.getChildNo());
        settlementDriver.setOrderGoodsNo(settlementDriverDetail.getOrderGoodsNo());
        settlementDriver.setOrderNo(settlementDriverDetail.getOrderNo());
        settlementDriver.setGoodsId(settlementDriverDetail.getGoodsId());
        settlementDriver.setGoodsName(settlementDriverDetail.getGoodsName());
        settlementDriver.setTruckNo(settlementDriverDetail.getTruckNo());
        settlementDriver.setFreightPrice(settlementDriverDetail.getFreightPrice());
        settlementDriver.setWeight(settlementDriverDetail.getWeight());
        settlementDriver.setFreight(settlementDriverDetail.getFreight());
        settlementDriver.setLossPrice(settlementDriverDetail.getLossPrice());
        settlementDriver.setLossWeight(settlementDriverDetail.getLossWeight());
        settlementDriver.setLoanFlag(settlementDriverDetail.getLoanFlag());
        settlementDriver.setLossFreight(settlementDriverDetail.getLossFreight());
        settlementDriver.setPrepayFreightFlag(settlementDriverDetail.getPrepayFreightFlag());
        settlementDriver.setSettlementFreight(settlementDriverDetail.getSettlementFreight());
        settlementDriver.setInvoiceType(settlementDriverDetail.getInvoiceType());
        settlementDriver.setSettlementPlatform(settlementDriverDetail.getInvoiceType() == 1 ?
                String.valueOf(SettlementPlatformEnum.Platform.WY.getCode()):
                String.valueOf(SettlementPlatformEnum.Platform.MSL.getCode()));

        settlementDriver.setStatus(SettlementDriverEnum.Status.DRIVER_UNCONFIRMED.getCode());

        settlementDriver.setInvoicingCompanyId(settlementDriverDetail.getInvoicingCompanyId());
        settlementDriver.setInvoicingCompanyShorterName(settlementDriverDetail.getInvoicingCompanyShorterName());
        settlementDriver.setInvoicingCompanyGroupCode(settlementDriverDetail.getInvoicingCompanyGroupCode());
        settlementDriver.setPlatformServiceFeeRate(settlementDriverDetail.getPlatformServiceFeeRate());
        settlementDriver.setPlatformServiceFee(settlementDriverDetail.getPlatformServiceFee());

        settlementDriverDao.saveEntity(settlementDriver);

        settlementDriverDetail.setSettlementNo(settlementDriver.getSettlementNo());
        settlementDriverDetailDao.updateSettlementNo(settlementDriverDetail);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void settle(SettlementSettleMqParam mq) {
        OrderChild orderChild = orderChildDao.getByChildNo(mq.getChildNo()).get();

        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao.getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao.getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        // 网运单
        orderChildSyncTransportListener.extracted(orderChild, settlementOwnerDetail, settlementDriverDetail, mq.getInvoiceType(), mq.getRemark());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void invoiceTypeSync(SettlementInvoiceTypeSyncMqParam mq) {
        OrderChild orderChild = orderChildDao.getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao
                .getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if (!Objects.equals(settlementOwnerDetail.getInvoiceChannel(), SettlementOwnerDetailEnum.InvoiceChannel.BROKER.getCode())){
            return;
        }
        if (settlementOwnerDetail.getInvoiceType() != null) {return;}
        if (!Objects.equals(settlementOwnerDetail.getInvoiceTypeStatus(), SettlementOwnerDetailEnum.InvoiceTypeStatus.PROCESSING.getCode())){
            return;
        }

        try {
            // 获取状态
            TransportVO result = brokerService.getOrderChildStatus(mq.getChildNo());
            if (result == null){
                log.info("运单号 {} 未找到运单信息",mq.getChildNo());
                return;
            }

            String remark = "";
            Integer invoiceType = SettlementOwnerEnum.InvoiceType.ONLINE.getCode();
//            if (Objects.equals(result.getRiskStatus(), 1) || Objects.equals(result.getRiskStatus(), 2)) {
//                invoiceType = SettlementOwnerEnum.InvoiceType.ORDINARY.getCode();
//                remark += result.getRiskReason();
//            }

            if (Objects.equals(result.getSyncStatus(), 0)) {

                return;
            }
            // 同步失败
            else if (Objects.equals(result.getSyncStatus(), 2)) {

                // 更新状态
                settlementOwnerDetail.setInvoiceTypeStatus(SettlementOwnerDetailEnum.InvoiceTypeStatus.FAIL.getCode());
                settlementOwnerDetailDao.updateInvoiceTypeStatus(settlementOwnerDetail);

                SettlementOrderChildRisk settlementOrderChildRisk = settlementOrderChildRiskDao.findLastByChildNo(mq.getChildNo()).orNull();
                if (settlementOrderChildRisk!=null
                        && Objects.equals(settlementOrderChildRisk.getStatus(), SettlementOrderChildRiskEnum.Status.INIT.getCode())){
                    return;
                }
                settlementOrderChildRisk = new SettlementOrderChildRisk();

                settlementOrderChildRisk.setChildNo(orderChild.getChildNo());
                settlementOrderChildRisk.setTruckNo(orderChild.getTruckNo());
                settlementOrderChildRisk.setDriverName(orderChild.getDriverName());
                settlementOrderChildRisk.setDriverMobile(orderChild.getDriverMobile());
                settlementOrderChildRisk.setGoodsName(orderChild.getGoodsName());
                settlementOrderChildRisk.setInvoiceType(settlementOwnerDetail.getInvoiceType());
                settlementOrderChildRisk.setPoundAuditTime(settlementOwnerDetail.getPoundAuditTime());
                settlementOrderChildRisk.setRiskType(SettlementOrderChildRiskEnum.RiskType.SYNC_FAIL.getCode());
                settlementOrderChildRisk.setRiskRemark(result.getSyncMsg());
                settlementOrderChildRiskDao.saveEntity(settlementOrderChildRisk);

                settlementPostService.riskAdd(settlementOrderChildRisk.getId());

                return;
            }
            else {
                // 更新状态
                settlementOwnerDetail.setInvoiceTypeStatus(SettlementOwnerDetailEnum.InvoiceTypeStatus.SUCCESS.getCode());
                settlementOwnerDetailDao.updateInvoiceTypeStatus(settlementOwnerDetail);

                // 发送mq （结算）
                settlementMqService.settle(orderChild.getChildNo(), invoiceType, remark);
            }
        }catch (Exception e){
            log.info("结算获取状态失败， 运单号 {}",mq.getChildNo(),e);
        }
    }

    @Override
    public void driverPayAcceptSync(SettlementDriverPayAcceptSyncMqParam mq) {
        OrderChild orderChild = orderChildDao.getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao
                .getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if (!Objects.equals(settlementOwnerDetail.getInvoiceChannel(), SettlementOwnerDetailEnum.InvoiceChannel.BROKER.getCode())){
            return;
        }
        if (settlementOwnerDetail.getInvoiceType() == null) {return;}

        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao
                .getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if (!Objects.equals(settlementDriverDetail.getPayAcceptStatus(), SettlementDriverDetailEnum.PayAcceptStatus.ACCEPTING.getCode())){
            return;
        }

        SettlementDriver settlementDriver = settlementDriverDao
                .getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        try {
            // 获取状态
            TransportVO result = brokerService.getOrderChildStatus(mq.getChildNo());
            if (result == null){
                log.info("运单号 {} 未找到运单信息",mq.getChildNo());
                return;
            }

            if (Objects.equals(result.getSyncStatus(), 0)) {

                return;
            }

            else if (Objects.equals(result.getThirdPartyChildStatus(), 30)) {
                // 更新状态
                settlementDriverDetail.setPayAcceptStatus(SettlementDriverDetailEnum.PayAcceptStatus.ACCEPTED.getCode());
                settlementDriverDetailDao.updatePayAcceptStatus(settlementDriverDetail);

            }
        }catch (Exception e){
            log.info("结算获取支付受理状态失败， 运单号 {}",mq.getChildNo(),e);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void invoiceStatusSync(SettlementInvoiceStatusSyncMqParam mq) {
        OrderChild orderChild = orderChildDao.getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao
                .getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if (!Objects.equals(settlementOwnerDetail.getInvoiceChannel(), SettlementOwnerDetailEnum.InvoiceChannel.BROKER.getCode())){
            return;
        }
        if (Objects.equals(settlementOwnerDetail.getInvoiceType(), SettlementOwnerEnum.InvoiceType.ORDINARY.getCode())){
            // 普通单不同步状态
            return;
        }

        if (!Objects.equals(settlementOwnerDetail.getInvoiceStatus(), SettlementOwnerDetailEnum.InvoiceStatus.NO.getCode())){
            return;
        }

        // 获取状态
        TransportVO result = brokerService.getOrderChildStatus(mq.getChildNo());
        if (result == null){
            log.info("运单号 {} 未找到运单信息",mq.getChildNo());
            return;
        }

        // 同步失败
        if (Objects.equals(result.getSyncStatus(), 2)) {

            // 更新状态
            settlementOwnerDetail.setInvoiceTypeStatus(SettlementOwnerDetailEnum.InvoiceTypeStatus.FAIL.getCode());
            settlementOwnerDetailDao.updateInvoiceTypeStatus(settlementOwnerDetail);

            SettlementOrderChildRisk settlementOrderChildRisk = settlementOrderChildRiskDao.findLastByChildNo(mq.getChildNo()).orNull();
            if (settlementOrderChildRisk!=null
                    && Objects.equals(settlementOrderChildRisk.getStatus(), SettlementOrderChildRiskEnum.Status.INIT.getCode())){
                return;
            }
            settlementOrderChildRisk = new SettlementOrderChildRisk();
            settlementOrderChildRisk.setChildNo(orderChild.getChildNo());
            settlementOrderChildRisk.setTruckNo(orderChild.getTruckNo());
            settlementOrderChildRisk.setDriverName(orderChild.getDriverName());
            settlementOrderChildRisk.setDriverMobile(orderChild.getDriverMobile());
            settlementOrderChildRisk.setGoodsName(orderChild.getGoodsName());
            settlementOrderChildRisk.setInvoiceType(settlementOwnerDetail.getInvoiceType());
            settlementOrderChildRisk.setPoundAuditTime(settlementOwnerDetail.getPoundAuditTime());
            settlementOrderChildRisk.setRiskType(SettlementOrderChildRiskEnum.RiskType.SYNC_FAIL.getCode());
            settlementOrderChildRisk.setRiskRemark(result.getSyncMsg());
            settlementOrderChildRiskDao.saveEntity(settlementOrderChildRisk);

            settlementPostService.riskAdd(settlementOrderChildRisk.getId());

            return;
        }

        if (Objects.equals(result.getInvoiceStatus(), 1) ) {
            InvoicingStatusNotifyDTO invoicingStatusNotifyDTO = new InvoicingStatusNotifyDTO();
            invoicingStatusNotifyDTO.setChildNoList(Arrays.asList(mq.getChildNo()));

            ApplicationContextUtils.getBean(SettlementOwnerService.class)
                    .invoicingStatusNotify(invoicingStatusNotifyDTO);

            // 发送mq (运单更新)
            orderChildBrokerMqService.orderChildUpdate(settlementOwnerDetail.getChildNo());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void payStatusSync(SettlementPayStatusSyncMqParam mq) {
        OrderChild orderChild = orderChildDao
                .getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        OrderGoods orderGoods = orderGoodsDao
                .getByOrderGoodsNo(orderChild.getOrderGoodsNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao
                .getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if (!Objects.equals(settlementOwnerDetail.getInvoiceChannel(), SettlementOwnerDetailEnum.InvoiceChannel.BROKER.getCode())){
            return;
        }
        if (Objects.equals(settlementOwnerDetail.getInvoiceType(), SettlementOwnerEnum.InvoiceType.ORDINARY.getCode())){
            // 普通单不同步状态
            return;
        }

        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao
                .getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);


        OrderChildSyncTransportRecord orderChildSyncTransportRecord = orderChildSyncTransportRecordDao
                .getByChildNo(orderChild.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        if (!Objects.equals(orderChildSyncTransportRecord.getStatus(),
                OrderChildSyncTransportRecordEnum.Status.INIT.getCode())){
            return;
        }

        // 获取状态
        TransportVO result = brokerService.getOrderChildStatus(mq.getChildNo(), settlementOwnerDetail.getSettlementNo());
        if (result == null){
            log.info("运单号 {} 未找到运单信息",mq.getChildNo());
            return;
        }

        // 同步失败
        if (Objects.equals(result.getSyncStatus(), 2)) {

            // 更新状态
            settlementOwnerDetail.setInvoiceTypeStatus(SettlementOwnerDetailEnum.InvoiceTypeStatus.FAIL.getCode());
            settlementOwnerDetailDao.updateInvoiceTypeStatus(settlementOwnerDetail);

            SettlementOrderChildRisk settlementOrderChildRisk = settlementOrderChildRiskDao.findLastByChildNo(mq.getChildNo()).orNull();
            if (settlementOrderChildRisk!=null
                    && Objects.equals(settlementOrderChildRisk.getStatus(), SettlementOrderChildRiskEnum.Status.INIT.getCode())){
                return;
            }
            settlementOrderChildRisk = new SettlementOrderChildRisk();
            settlementOrderChildRisk.setChildNo(orderChild.getChildNo());
            settlementOrderChildRisk.setTruckNo(orderChild.getTruckNo());
            settlementOrderChildRisk.setDriverName(orderChild.getDriverName());
            settlementOrderChildRisk.setDriverMobile(orderChild.getDriverMobile());
            settlementOrderChildRisk.setGoodsName(orderChild.getGoodsName());
            settlementOrderChildRisk.setInvoiceType(settlementOwnerDetail.getInvoiceType());
            settlementOrderChildRisk.setPoundAuditTime(settlementOwnerDetail.getPoundAuditTime());
            settlementOrderChildRisk.setRiskType(SettlementOrderChildRiskEnum.RiskType.SYNC_FAIL.getCode());
            settlementOrderChildRisk.setRiskRemark(result.getSyncMsg());
            settlementOrderChildRiskDao.saveEntity(settlementOrderChildRisk);

            settlementPostService.riskAdd(settlementOrderChildRisk.getId());

            return;
        }

        if (Objects.equals(result.getSettleStatus(), 1) ) {

            if (Objects.equals(orderGoods.getPlatformFreightQuotationTaxType(),QuotationEnum.PlatformFreightQuotationTaxType.NO.getCode())
                    && Objects.equals(orderGoods.getSettlementWay(), SettlementWayEnum.WayType.UNLOAD_LOSS.getCode())) {
                settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);
                settlementDriverDetail.setPrepayFreightFlag(SettlementDriverEnum.PrepayFreightFlag.NO_PAY.getCode());
                settlementOwnerDetail.setFinalPaymentStatus(SettlementOwnerDetailEnum.FinalPaymentStatus.NO.getCode());

                //生成提现记录
                networkDriverRunningWaterRecordService.generateNetworkCaseOutRecord(settlementDriverDetail);
            }

            PayStatusNotifyDTO payStatusNotifyDTO = new PayStatusNotifyDTO();
            payStatusNotifyDTO.setChildNo(mq.getChildNo());
            orderChildSyncTransportRecordService.updateStatus(payStatusNotifyDTO);

            // 发送mq (结算单平台自动确认)
            settlementMqService.settlementPlatformAutoConfirmUpdate(settlementOwnerDetail.getSettlementNo());

            // 发送mq (运单更新)
            orderChildBrokerMqService.orderChildUpdate(settlementOwnerDetail.getChildNo());

        }
        else if (Objects.equals(result.getSettleStatus(), 3) ) {
            SettlementOrderChildRisk settlementOrderChildRisk = new SettlementOrderChildRisk();
            settlementOrderChildRisk.setChildNo(orderChild.getChildNo());
            settlementOrderChildRisk.setTruckNo(orderChild.getTruckNo());
            settlementOrderChildRisk.setDriverName(orderChild.getDriverName());
            settlementOrderChildRisk.setDriverMobile(orderChild.getDriverMobile());
            settlementOrderChildRisk.setGoodsName(orderChild.getGoodsName());
            settlementOrderChildRisk.setInvoiceType(settlementOwnerDetail.getInvoiceType());
            settlementOrderChildRisk.setPoundAuditTime(settlementOwnerDetail.getPoundAuditTime());
            settlementOrderChildRisk.setRiskType(SettlementOrderChildRiskEnum.RiskType.SETTLE_FAIL.getCode());
            settlementOrderChildRisk.setRiskRemark(result.getSettleMsg());
            settlementOrderChildRiskDao.saveEntity(settlementOrderChildRisk);

            settlementPostService.riskAdd(settlementOrderChildRisk.getId());
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void settlementDetailAdd(SettlementDetailAddMqParam mq) {
        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao
                .getEntityByKey(mq.getSettlementOwnerDetailId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao
                .getEntityByKey(mq.getSettlementDriverDetailId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        OrderChild orderChild = orderChildDao
                .getByChildNo(settlementDriverDetail.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        SettlementPlatformServiceFee settlementPlatformServiceFee = null;
        if (settlementDriverDetail.getPlatformServiceFee().compareTo(BigDecimal.ZERO) > 0) {
            settlementPlatformServiceFee = new SettlementPlatformServiceFee();
            settlementPlatformServiceFee.setChildNo(settlementDriverDetail.getChildNo());
            settlementPlatformServiceFee.setDriverUserNo(settlementDriverDetail.getDriverUserNo());
            settlementPlatformServiceFee.setDriverName(settlementDriverDetail.getDriverName());
            settlementPlatformServiceFee.setDriverMobile(orderChild.getDriverMobile());
            settlementPlatformServiceFee.setSendAddressId(orderChild.getSendAddressId());
            settlementPlatformServiceFee.setSendAddress(orderChild.getSendAddress());
            settlementPlatformServiceFee.setReceiveAddressId(orderChild.getReceiveAddressId());
            settlementPlatformServiceFee.setReceiveAddress(orderChild.getReceiveAddress());
            settlementPlatformServiceFee.setTruckNo(orderChild.getTruckNo());
            settlementPlatformServiceFee.setSettlementFreight(settlementDriverDetail.getSettlementFreight());
            settlementPlatformServiceFee.setInvoiceServiceFeeRate(settlementDriverDetail.getPlatformServiceFeeRate());
            settlementPlatformServiceFee.setInvoiceServiceFee(settlementDriverDetail.getPlatformServiceFee());

            // 平台服务费
            orderChild.setPlatformServiceFee(settlementDriverDetail.getPlatformServiceFee());
        }

        orderChildDao.updatePlatformServiceFee(orderChild);
        if (settlementPlatformServiceFee != null) {
            settlementPlatformServiceFeeDao.saveEntity(settlementPlatformServiceFee);
        }

        // 预付运费判断
        if (settlementDriverDetail.getSettlementFreight().compareTo(BigDecimal.ZERO) <= 0) {

//            // 转普通单
//            settlementOwnerDetail.setInvoiceType(SettlementOwnerEnum.InvoiceType.ORDINARY.getCode());
//            settlementOwnerDetail.setInvoicingCompanyId(null);
//            settlementOwnerDetail.setInvoicingCompanyShorterName(null);
//            settlementOwnerDetail.setInvoicingCompanyGroupCode(null);
            settlementOwnerDetail.setPrepayFreight(BigDecimal.ZERO);

//            settlementDriverDetail.setInvoiceType(settlementOwnerDetail.getInvoiceType());
//            settlementDriverDetail.setInvoicingCompanyId(settlementOwnerDetail.getInvoicingCompanyId());
//            settlementDriverDetail.setInvoicingCompanyShorterName(settlementOwnerDetail.getInvoicingCompanyShorterName());
//            settlementDriverDetail.setInvoicingCompanyGroupCode(settlementOwnerDetail.getInvoicingCompanyGroupCode());
            settlementDriverDetail.setPrepayFreightFlag(SettlementDriverEnum.PrepayFreightFlag.NO_PAY.getCode());

            settlementOwnerDetailDao.updatePreFreight(settlementOwnerDetail);
            settlementDriverDetailDao.updatePreFreight(settlementDriverDetail);
        }

        if (Objects.equals(settlementOwnerDetail.getReportFlag(), com.clx.order.enums.OrderEnum.ReportFlag.NO.getCode())){
            // 转普通单
            settlementOwnerDetail.setInvoiceType(SettlementOwnerEnum.InvoiceType.ORDINARY.getCode());
            settlementOwnerDetail.setInvoicingCompanyId(null);
            settlementOwnerDetail.setInvoicingCompanyShorterName(null);
            settlementOwnerDetail.setInvoicingCompanyGroupCode(null);

            settlementDriverDetail.setInvoiceType(settlementOwnerDetail.getInvoiceType());
            settlementDriverDetail.setInvoicingCompanyId(settlementOwnerDetail.getInvoicingCompanyId());
            settlementDriverDetail.setInvoicingCompanyShorterName(settlementOwnerDetail.getInvoicingCompanyShorterName());
            settlementDriverDetail.setInvoicingCompanyGroupCode(settlementOwnerDetail.getInvoicingCompanyGroupCode());

            settlementOwnerDetailDao.updatePreFreight(settlementOwnerDetail);
            settlementDriverDetailDao.updatePreFreight(settlementDriverDetail);

        }
        else {
            // 发送mq (更新无车承运)
            orderChildBrokerMqService.orderChildSync(orderChild.getChildNo());
        }

//
//        log.info("更新网络标识 {} ",orderChild.getChildNo());
//        // 更新网络标识
//        settlementService.updateSettlementDetailInvoiceType(settlementOwnerDetail.getChildNo(), SettlementOwnerEnum.InvoiceType.ORDINARY.getCode());
    }

    @Override
    public void settlementDriverNotify(String childNo,Integer payType,String payErrorMsg){

        //运单状态修改为完成
        OrderChild orderChild = orderChildDao.getByChildNo(childNo).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
        SettlementDriver settlementDriver = settlementDriverDao.getByChildNo(childNo).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);

        if(1 == payType){
            orderChild.setStatus(OrderChildEnum.Status.COMPLETE.getCode());
            orderChild.setSettleTime(LocalDateTime.now());
            orderChild.setFinishTime(orderChild.getSettleTime());
            orderChildDao.updateSettlement(orderChild);

            settlementDriverDao.updateStatus(settlementDriver.getId(),SettlementDriverEnum.Status.SETTLED.getCode());

            // 日志
            orderChildLogService.saveDriverOrderChildLog(childNo, OrderChildLogEnum.Type.COMPLETE.getCode(),
                    OrderChildLogEnum.Type.COMPLETE.getMsg(), 0L, "系统");

            settlementPostService.updateDriverPaySuccess(childNo);
        }else{
            settlementDriverDao.updatePayErrorMsg(settlementDriver.getId(),payErrorMsg);
        }

    }

    /**
     * 车主结算单自动支付
     */
    @Override
    public String paySettlementDriver(SettlementDriverDetail detail){
        String uuid = UUID.randomUUID().toString();
        String key = RedissonConstants.SETTLEMENT_OWNER_BATCH_PAY_ID_LOCK + detail.getId();
        try{
            boolean flag = redisUtil.lock(key, uuid,180);
            if(!flag){
                return "获取支付锁失败，操作频繁，请稍后重试";
            }

            DriverInfoFeignVo driverInfoFeignVo = driverService.getDriverInfo(detail.getDriverUserNo()).orElseThrow(ResultCodeEnum.FAIL);
            PayParam noCheckPwd = null ;
            if(detail.getSettlementFreight().compareTo(BigDecimal.ZERO) > 0){
                noCheckPwd = PayParam.builder().from(mslPaymentConfig.getTransportWalletCode())
                        .to(driverInfoFeignVo.getWalletCode())
                        .figure(detail.getSettlementFreight().intValue())
                        .tradeNo(detail.getChildNo())
                        .tradeId(detail.getChildNo())
                        .pwd("noCheckPwd")
                        .remark(PayRemarkEnum.toString(PayRemarkEnum.FREIGHT_TO_OWNER.getValue()))
                        .build();
            }else{
                BigDecimal freight = detail.getSettlementFreight().abs();
                noCheckPwd = PayParam.builder().from(driverInfoFeignVo.getWalletCode())
                        .to(mslPaymentConfig.getTransportWalletCode())
                        .figure(freight.intValue())
                        .tradeNo(detail.getChildNo())
                        .tradeId(detail.getChildNo())
                        .pwd("noCheckPwd")
                        .remark(PayRemarkEnum.toString(PayRemarkEnum.FREIGHT_TO_OWNER.getValue()))
                        .build();
            }
            //支付司机运费
            Result result = null;
            String msg  = null;
            try{
                result = paymentService.paymentWallet(noCheckPwd);
            }catch (Exception e){
                settlementDriverNotify(detail.getChildNo(),0,e.getMessage());
                msg = e.getMessage();
            }
            //支付平台服务费
            try{
                OrderChild orderChild = orderChildDao.getByChildNo(detail.getChildNo()).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
                if (Objects.nonNull(orderChild.getPlatformServiceFee()) &&
                        !Objects.equals(orderChild.getPlatformServiceFee().intValue(), 0)) {
                    PayPlatformFeeParam payPlatformFeeParam = PayPlatformFeeParam.builder()
                            .figure(orderChild.getPlatformServiceFee().intValue())
                            .tradeNo(detail.getChildNo())
                            .build();
                    result = paymentService.paymentCompletePlatformFee(payPlatformFeeParam);
                }
            }catch (Exception e){
                log.error("支付平台服务费异常 {}",e);
            }
            if(Objects.nonNull(result)){
                settlementDriverNotify(detail.getChildNo(),0,result.getMsg());
            }
            return msg;
        }catch (Exception e){
            log.warn("结算单支付上锁失败，结算单ID：{},异常原因:{}", detail.getId(), ExceptionUtils.getStackTrace(e));
            //解锁
            redisUtil.unlock(key,uuid);
            throw new ServiceSystemException(PerformanceResultEnum.TRY_LOCK_ERROR);
        }
    }

    /**
     * 月结初始化
     */
    private String settlementPeriodMonthInit(SettlementOwnerDetail settlementOwnerDetail,
                                             LocalDateTime settlementPeriodTime,
                                             Integer settlementPeriodType,
                                             OwnerInfoFeignVO ownerInfo){


        FeignOrderInfoVO orderInfo = orderService.getOrderInfo(settlementOwnerDetail.getOrderNo())
                .orElseThrow(PerformanceResultEnum.ORDER_INVALID);

        //获取所有detail

        SettlementOwner settlementOwner = new SettlementOwner();

        String settlementNo = settlementNoGenerate();

        settlementOwner.setSettlementNo(settlementNo);
        settlementOwner.setOwnerUserNo(settlementOwnerDetail.getOwnerUserNo());
        settlementOwner.setOwnerName(settlementOwnerDetail.getOwnerName());
        settlementOwner.setOrderNo(settlementOwnerDetail.getOrderNo());

        settlementOwner.setSettlementPeriodType(settlementPeriodType);
        settlementOwner.setSettlementPeriodTime(settlementPeriodTime);

        settlementOwner.setWeight(settlementOwnerDetail.getWeight());
        settlementOwner.setFreight(settlementOwnerDetail.getFreight());
        settlementOwner.setLossWeight(settlementOwnerDetail.getLossWeight());
        settlementOwner.setLossFreight(settlementOwnerDetail.getLossFreight());
        settlementOwner.setSettlementFreight(settlementOwnerDetail.getSettlementFreight());
        settlementOwner.setLoanFreight(settlementOwnerDetail.getLoanFreight());

        settlementOwner.setInvoiceType(settlementOwnerDetail.getInvoiceType());
        settlementOwner.setInvoiceFreight(settlementOwnerDetail.getInvoiceFreight());

        settlementOwner.setPrepayFreight(settlementOwnerDetail.getPrepayFreight());
        settlementOwner.setStatus(SettlementOwnerEnum.Status.TO_BE_LOCKED.getCode());
        settlementOwner.setInvoiceStatus(SettlementOwnerEnum.InvoiceStatus.NOT_INVOICE.getCode());

        settlementOwner.setCompanyName(ownerInfo.getCompanyName());
        settlementOwner.setCompanyTaxCode(ownerInfo.getCompanyTaxCode());
        settlementOwner.setCompanyAddress(ownerInfo.getCompanyAddress());
        settlementOwner.setCompanyMobile(ownerInfo.getCompanyTelephone());
        settlementOwner.setCompanyBankNo(ownerInfo.getCompanyBankAccount());
        settlementOwner.setCompanyBankName(ownerInfo.getCompanyOpenBank());

        settlementOwner.setCompanyContact(ownerInfo.getContactsName());
        settlementOwner.setCompanyContactMobile(ownerInfo.getContactsTelephone());
        settlementOwner.setCompanyContactAddress(ownerInfo.getContactsAddress());
        settlementOwner.setSettlementWay(settlementOwnerDetail.getSettlementWay());
        //设置开票公司
        settlementOwner.setInvoicingCompanyId(settlementOwnerDetail.getInvoicingCompanyId());
        settlementOwner.setInvoicingCompanyShorterName(settlementOwnerDetail.getInvoicingCompanyShorterName());
        settlementOwner.setInvoicingCompanyGroupCode(settlementOwnerDetail.getInvoicingCompanyGroupCode());
        settlementOwner.setReportFlag(orderInfo.getReportFlag());
        // 开票服务费
        settlementOwner.setInvoiceServiceFee(settlementOwnerDetail.getInvoiceServiceFee());

        settlementOwner.setDriverFreight(settlementOwnerDetail.getDriverFreight());
        settlementOwner.setLoadNet(settlementOwnerDetail.getLoadNet());
        settlementOwner.setUnloadNet(settlementOwnerDetail.getUnloadNet());

        settlementOwnerDao.saveEntity(settlementOwner);

        //保存结算单日志----创建结算单
        settlementLogService.saveSettlementLog(settlementNo,
                SettlementLogEnum.Type.CREATE_SETTLEMENT.getCode(),SettlementLogEnum.Type.CREATE_SETTLEMENT.getMsg(),
                OrderChildLogEnum.CreateType.PLATFORM.getCode(),0L,"系统");

        return settlementNo;
    }

    /**
     * 月结更新
     */
    private void settlementPeriodMonthUpdate(SettlementOwner settlementOwner, SettlementOwnerDetail settlementOwnerDetail){

        settlementOwner.setWeight(settlementOwnerDetail.getWeight());
        settlementOwner.setFreight(settlementOwnerDetail.getFreight());
        settlementOwner.setLossWeight(settlementOwnerDetail.getLossWeight());
        settlementOwner.setLossFreight(settlementOwnerDetail.getLossFreight());
        settlementOwner.setPrepayFreight(settlementOwnerDetail.getPrepayFreight());
        settlementOwner.setSettlementFreight(settlementOwnerDetail.getSettlementFreight());
        settlementOwner.setLoanFreight(settlementOwnerDetail.getLoanFreight());
        settlementOwner.setInvoiceFreight(settlementOwnerDetail.getInvoiceFreight());
        settlementOwner.setInvoiceServiceFee(settlementOwnerDetail.getInvoiceServiceFee());

        settlementOwner.setDriverFreight(settlementOwnerDetail.getDriverFreight());
        settlementOwner.setLoadNet(settlementOwnerDetail.getLoadNet());
        settlementOwner.setUnloadNet(settlementOwnerDetail.getUnloadNet());

        List<SettlementOwnerDetail> details = settlementOwnerDetailDao.getBySettlementNo(settlementOwner.getSettlementNo());

        details.forEach(item->{
            settlementOwner.setWeight(settlementOwner.getWeight().add(item.getWeight()));
            settlementOwner.setFreight(settlementOwner.getFreight().add(item.getFreight()));
            settlementOwner.setLossWeight(settlementOwner.getLossWeight().add(item.getLossWeight()));
            settlementOwner.setLossFreight(settlementOwner.getLossFreight().add(item.getLossFreight()));
            settlementOwner.setLoanFreight(settlementOwner.getLoanFreight().add(item.getLoanFreight()));
            settlementOwner.setPrepayFreight(settlementOwner.getPrepayFreight().add(item.getPrepayFreight()));
            settlementOwner.setSettlementFreight(settlementOwner.getSettlementFreight().add(item.getSettlementFreight()));
            settlementOwner.setInvoiceFreight(settlementOwner.getInvoiceFreight().add(item.getInvoiceFreight()));
            settlementOwner.setInvoiceServiceFee(settlementOwner.getInvoiceServiceFee().add(item.getInvoiceServiceFee()));

            settlementOwner.setDriverFreight(settlementOwner.getDriverFreight().add(item.getDriverFreight()));
            settlementOwner.setLoadNet(settlementOwner.getLoadNet().add(item.getLoadNet()));
            settlementOwner.setUnloadNet(settlementOwner.getUnloadNet().add(item.getUnloadNet()));
        });

        settlementOwnerDao.updateSettlementPeriodMonth(settlementOwner);
    }

    /**
     * 月结更新
     */
    private void settlementStatisticsSeparate(SettlementOwnerDetail settlementOwnerDetail){
        String settlementNo = settlementOwnerDetail.getSettlementNo();
        SettlementOwner settlementOwner = settlementOwnerDao
                .findBySettlementNo(settlementNo).orElseThrow(ResultEnum.DATA_NOT_FIND);

        settlementOwner.setWeight(BigDecimal.ZERO);
        settlementOwner.setFreight(BigDecimal.ZERO);
        settlementOwner.setLossWeight(BigDecimal.ZERO);
        settlementOwner.setLossFreight(BigDecimal.ZERO);
        settlementOwner.setPrepayFreight(BigDecimal.ZERO);
        settlementOwner.setSettlementFreight(BigDecimal.ZERO);
        settlementOwner.setLoanFreight(BigDecimal.ZERO);
        settlementOwner.setInvoiceFreight(BigDecimal.ZERO);
        settlementOwner.setInvoiceServiceFee(BigDecimal.ZERO);

        settlementOwner.setDriverFreight(BigDecimal.ZERO);
        settlementOwner.setLoadNet(BigDecimal.ZERO);
        settlementOwner.setUnloadNet(BigDecimal.ZERO);

        List<SettlementOwnerDetail> details = settlementOwnerDetailDao.getBySettlementNo(settlementOwner.getSettlementNo());
        details.stream().filter(item->!Objects.equals(item.getChildNo(), settlementOwnerDetail.getChildNo()))
                .collect(Collectors.toList())
                .forEach(item->{
            settlementOwner.setWeight(settlementOwner.getWeight().add(item.getWeight()));
            settlementOwner.setFreight(settlementOwner.getFreight().add(item.getFreight()));
            settlementOwner.setLossWeight(settlementOwner.getLossWeight().add(item.getLossWeight()));
            settlementOwner.setLossFreight(settlementOwner.getLossFreight().add(item.getLossFreight()));
            settlementOwner.setLoanFreight(settlementOwner.getLoanFreight().add(item.getLoanFreight()));
            settlementOwner.setPrepayFreight(settlementOwner.getPrepayFreight().add(item.getPrepayFreight()));
            settlementOwner.setSettlementFreight(settlementOwner.getSettlementFreight().add(item.getSettlementFreight()));
            settlementOwner.setInvoiceFreight(settlementOwner.getInvoiceFreight().add(item.getInvoiceFreight()));
            settlementOwner.setInvoiceServiceFee(settlementOwner.getInvoiceServiceFee().add(item.getInvoiceServiceFee()));

            settlementOwner.setDriverFreight(settlementOwner.getDriverFreight().add(item.getDriverFreight()));
            settlementOwner.setLoadNet(settlementOwner.getLoadNet().add(item.getLoadNet()));
            settlementOwner.setUnloadNet(settlementOwner.getUnloadNet().add(item.getUnloadNet()));
        });

        settlementOwnerDao.updateSettlementPeriodMonth(settlementOwner);

        settlementOwnerDetail.setSettlementNo(null);
        settlementOwnerDetail.setSeparateRemark("系统自动拆单（原结算单号"+settlementNo+"）");

        settlementOwnerDetailDao.updateClearSettlementNo(settlementOwnerDetail);
    }

    /**
     * 创建结算单号
     */
    @Override
    public String settlementNoGenerate(){
        return uniqueOrderNumService.getUniqueOrderNum(com.msl.common.utils.LocalDateTimeUtils.convertLocalDateTimeToString(LocalDateTime.now(), com.msl.common.utils.LocalDateTimeUtils.DATE_DAY));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void riskAdd(SettlementOrderChildRiskAddMqParam mq) {
        SettlementOrderChildRisk settlementOrderChildRisk = settlementOrderChildRiskDao
                .getById(mq.getId()).orElseThrow(ResultEnum.DATA_NOT_FIND);
        if (Objects.equals(settlementOrderChildRisk.getStatus(), SettlementOrderChildRiskEnum.Status.PROCESSED.getCode())) {
            return;
        }

        OrderChild orderChild = orderChildDao
                .getByChildNo(settlementOrderChildRisk.getChildNo()).orElseThrow(ResultEnum.DATA_NOT_FIND);

        InvoicingCompanyVO invoicingCompanyByGroupCode = invoicingCompanyService
                .getInvoicingCompanyByGroupCode(orderChild.getInvoicingCompanyGroupCode());
        if (!Objects.equals(invoicingCompanyByGroupCode.getRiskProcessType(), InvoicingCompanyEnum.RiskProcessType.AUTO.getCode())) {
            return;
        }

        // 转普通单
        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao
                .getByChildNo(settlementOrderChildRisk.getChildNo()).orElseThrow(ResultEnum.DATA_NOT_FIND);
        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao
                .getByChildNo(settlementOrderChildRisk.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        settlementOrderChildRisk.setStatus(SettlementOrderChildRiskEnum.Status.PROCESSED.getCode());
        settlementOrderChildRisk.setProcessMethod(SettlementOrderChildRiskEnum.ProcessMethod.CONVERT_ORDINARY.getCode());
        settlementOrderChildRisk.setProcessBy("系统");
        settlementOrderChildRisk.setProcessTime(LocalDateTime.now());

        settlementOwnerDetail.setInvoiceType(SettlementOwnerEnum.InvoiceType.ORDINARY.getCode());
        settlementOwnerDetail.setInvoicingCompanyId(null);
        settlementOwnerDetail.setInvoicingCompanyShorterName(null);
        settlementOwnerDetail.setInvoicingCompanyGroupCode(null);
        settlementOwnerDetail.setInvoiceTypeStatus(SettlementOwnerDetailEnum.InvoiceTypeStatus.SUCCESS.getCode());
        settlementOwnerDetail.setInvoiceTypeModifiedTime(LocalDateTime.now());
        settlementOwnerDetailDao.updateConvertOrdinary(settlementOwnerDetail);

        settlementDriverDetail.setInvoiceType(settlementOwnerDetail.getInvoiceType());
        settlementDriverDetail.setInvoicingCompanyId(settlementOwnerDetail.getInvoicingCompanyId());
        settlementDriverDetail.setInvoicingCompanyShorterName(settlementOwnerDetail.getInvoicingCompanyShorterName());
        settlementDriverDetail.setInvoicingCompanyGroupCode(settlementOwnerDetail.getInvoicingCompanyGroupCode());
        settlementDriverDetailDao.updateConvertOrdinary(settlementDriverDetail);

        settlementOrderChildRisk.setInvoiceType(settlementOwnerDetail.getInvoiceType());

        settlementOrderChildRiskDao.updateProcess(settlementOrderChildRisk);

        // 发送mq (风控处理)
        settlementMqService.riskProcess(settlementOrderChildRisk.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void riskProcess(SettlementOrderChildRiskProcessMqParam mq) {
        SettlementOrderChildRisk settlementOrderChildRisk = settlementOrderChildRiskDao.getById(mq.getId()).orElseThrow(ResultEnum.DATA_NOT_FIND);
        String childNo = settlementOrderChildRisk.getChildNo();

        if (Objects.equals(settlementOrderChildRisk.getProcessMethod(), SettlementOrderChildRiskEnum.ProcessMethod.CONVERT_ORDINARY.getCode())){
            SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao.getByChildNo(childNo).orNull();

            // 已进结算单需拆单
            if (settlementOwnerDetail !=null && StringUtils.isNotBlank(settlementOwnerDetail.getSettlementNo())) {
                // 发送mq 结算统计
                settlementMqService.settlementStatistics(childNo, SettlementStatisticsMqParam.Type.SEPARATE.getCode());
            }

            // 发送mq (车主结算)
            settlementMqService.settlementDriverSettle(childNo);

            // 发送mq (运单更新)
            orderChildBrokerMqService.orderChildUpdate(childNo);
        }
        else if (Objects.equals(settlementOrderChildRisk.getProcessMethod(), SettlementOrderChildRiskEnum.ProcessMethod.SYNC_RETRY.getCode())){

            // 发送mq (更新无车承运)
            orderChildBrokerMqService.orderChildSync(childNo);
        }

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void invoiceCompanyUpdate(SettlementOwnerDetialInvoiceCompanyUpdateMqParam mq) {

        SettlementOwnerDetail settlementOwnerDetail = settlementOwnerDetailDao
                .findById(mq.getId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);
        // 只处理普通单
        if (!Objects.equals(settlementOwnerDetail.getInvoiceType(), SettlementOwnerEnum.InvoiceType.ORDINARY.getCode())){
            return;
        }
        String childNo = settlementOwnerDetail.getChildNo();
        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao
                .getByChildNo(childNo).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        SettlementDriver settlementDriver = settlementDriverDao
                .getByChildNo(childNo).orNull();

        OrderChild orderChild = orderChildDao
                .getByChildNo(childNo).orElseThrow(PerformanceResultEnum.ORDER_CHILD_NO_FOUND);
        OrderGoods orderGoods = orderGoodsDao
                .getByOrderGoodsNo(orderChild.getOrderGoodsNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        // 查询开票公司
        InvoicingCompanyVO invoiceCompany = invoicingCompanyService.getInvoicingCompany(
                settlementOwnerDetail.getInvoicingCompanyId()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        // 开票服务率
        settlementOwnerDetail.setInvoiceServiceFeeRate(BigDecimal.ZERO);
        if (Objects.equals(invoiceCompany.getQuotationType(), InvoicingCompanyEnum.TaxType.TAX_EXCLUDED.getCode())) {
            settlementOwnerDetail.setInvoiceServiceFeeRate(
                    invoiceCompany.getServiceFeeRate() == null ? BigDecimal.ZERO : invoiceCompany.getServiceFeeRate());
        }
        // 开票服务费
        settlementOwnerDetail.setInvoiceServiceFee(
                settlementCommonService.invoiceServiceFeeCalc(orderChild.getSettlementWay(), settlementOwnerDetail));
        // 开票金额
        settlementOwnerDetail.setInvoiceFreight(
                settlementCommonService.invoiceFreightCalc(orderChild.getSettlementWay(),
                        orderGoods.getInvoiceServiceFeeRate(), settlementOwnerDetail));
        // 结算金额
        settlementOwnerDetail.setSettlementFreight(settlementCommonService.settlementFreightCalc(orderChild.getSettlementWay(), settlementOwnerDetail));
        if (settlementOwnerDetail.getSettlementFreight().compareTo(BigDecimal.ZERO) == 0) {
            settlementOwnerDetail.setFinalPaymentStatus(SettlementOwnerDetailEnum.FinalPaymentStatus.NO_REQUIRE.getCode());
        }

        if (settlementOwnerDetail.getInvoiceFreight().compareTo(BigDecimal.ZERO) <= 0) {
            settlementOwnerDetail.setInvoiceStatus(SettlementOwnerDetailEnum.InvoiceStatus.NO_INVOICE.getCode());
        }
        settlementDriverDetail.setInvoicingCompanyId(settlementOwnerDetail.getInvoicingCompanyId());
        settlementDriverDetail.setInvoicingCompanyShorterName(settlementOwnerDetail.getInvoicingCompanyShorterName());
        settlementDriverDetail.setInvoicingCompanyGroupCode(settlementOwnerDetail.getInvoicingCompanyGroupCode());

        log.info("当前货主结算信息{},车主结算信息：{}", JSONUtil.parse(settlementOwnerDetail), JSONUtil.parse(settlementDriverDetail));
        settlementOwnerDetailDao.updateInvoiceType(settlementOwnerDetail);
        settlementDriverDetailDao.updateInvoiceTypeAndPrepayFreightFlag(settlementDriverDetail);

        if (settlementDriver != null) {
            settlementDriver.setInvoicingCompanyId(settlementDriverDetail.getInvoicingCompanyId());
            settlementDriver.setInvoicingCompanyShorterName(settlementDriverDetail.getInvoicingCompanyShorterName());
            settlementDriver.setInvoicingCompanyGroupCode(settlementDriverDetail.getInvoicingCompanyGroupCode());
        }

        if (Objects.equals(settlementOwnerDetail.getReportFlag(), com.clx.order.enums.OrderEnum.ReportFlag.NO.getCode())){
            // 网运单转普通单
            orderChildSyncTransportListener.extracted(orderChild, settlementOwnerDetail, settlementDriverDetail, settlementOwnerDetail.getInvoiceType(), null);

            if (settlementDriver != null) {
                settlementDriver.setPrepayFreightFlag(settlementDriverDetail.getPrepayFreightFlag());
                settlementDriverDao.updateInvoiceCompany(settlementDriver);
            }

            return;
        }

        SettlementOrderChildRisk settlementOrderChildRisk = settlementOrderChildRiskDao
                .findLastByChildNo(childNo).orElseThrow(ResultEnum.DATA_NOT_FIND);
        if (settlementOrderChildRisk != null){
            // 网运单转普通单
            orderChildSyncTransportListener.extracted(orderChild, settlementOwnerDetail, settlementDriverDetail, settlementOwnerDetail.getInvoiceType(), settlementOrderChildRisk.getRiskRemark());

            if (settlementDriver != null) {
                settlementDriver.setPrepayFreightFlag(settlementDriverDetail.getPrepayFreightFlag());
                settlementDriverDao.updateInvoiceCompany(settlementDriver);
            }

            // 发送mq (更新无车承运)
            orderChildBrokerMqService.orderChildUpdate(childNo);
            return;
        }

        if (settlementDriver != null) {
            settlementDriver.setPrepayFreightFlag(settlementDriverDetail.getPrepayFreightFlag());
            settlementDriverDao.updateInvoiceCompany(settlementDriver);
        }

        //普通单解冻
        applicationEventPublisher.publishEvent(new OwnerLoanThawEvent(this, childNo));
        // 发送mq 结算统计
        settlementMqService.settlementStatistics(childNo);

        // 发送mq (更新无车承运)
        orderChildBrokerMqService.orderChildUpdate(settlementOwnerDetail.getChildNo());

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void settlementPlatformAutoConfirm(SettlementPlatformAutoConfirmMqParam mq) {
        SettlementOwner settlementOwner = settlementOwnerDao
                .findBySettlementNo(mq.getSettlementNo()).orElseThrow(ResultEnum.DATA_NOT_FIND);

        if (!Objects.equals(settlementOwner.getStatus(), SettlementOwnerEnum.Status.PLATFORM_TO_BE_CONFIRMED.getCode())){
            return;
        }

        // 所有运单支付完成，修改状态待货主确认
        List<SettlementOwnerDetail> list = settlementOwnerDetailDao.getBySettlementNo(settlementOwner.getSettlementNo());
        if (list.isEmpty()) {return;}
        Optional<SettlementOwnerDetail> optional = list.stream()
                .filter(item -> Objects.equals(item.getPayStatus(), SettlementOwnerDetailEnum.PayStatus.NO.getCode())).findFirst();
        if (optional.isPresent()) {return;}

        settlementOwner.setStatus(SettlementOwnerEnum.Status.OWNER_TO_BE_CONFIRMED.getCode());
        settlementOwnerDao.updateStatus(settlementOwner);
    }

    @Override
    public void settlementInvoiceStatusUpdate(SettlementInvoiceStatusUpdateMqParam mq) {
        SettlementOwner settlementOwner = settlementOwnerDao.findBySettlementNo(mq.getSettlementNo()).orElseThrow(ResultEnum.DATA_NOT_FIND);
        if (!Objects.equals(settlementOwner.getStatus(), SettlementOwnerEnum.Status.COMPLETED.getCode())){
            return;
        }
        if (Objects.equals(settlementOwner.getInvoiceStatus(), SettlementOwnerEnum.InvoiceStatus.INVOICED.getCode())){
            return;
        }

        List<SettlementOwnerDetail> list = settlementOwnerDetailDao.getBySettlementNo(settlementOwner.getSettlementNo());

        // 无需开票运单
        List<SettlementOwnerDetail> list1 = list.stream()
                .filter(item -> Objects.equals(item.getInvoiceStatus(),SettlementOwnerDetailEnum.InvoiceStatus.NO.getCode())
                        && item.getInvoiceFreight().compareTo(BigDecimal.ZERO) <= 0).collect(Collectors.toList());

        // 需要开票运单
        List<SettlementOwnerDetail> list2 = list.stream()
                .filter(item -> Objects.equals(item.getInvoiceStatus(),SettlementOwnerDetailEnum.InvoiceStatus.NO.getCode())
                        && item.getInvoiceFreight().compareTo(BigDecimal.ZERO) > 0).collect(Collectors.toList());
        // 已开票运单
        List<SettlementOwnerDetail> list3 = list.stream()
                .filter(item -> Objects.equals(item.getInvoiceStatus(),SettlementOwnerDetailEnum.InvoiceStatus.YES.getCode()))
                .collect(Collectors.toList());



        if (!list1.isEmpty()) {
            settlementOwnerDetailDao
                    .updateInvoiceStatusByIdList(list1.stream().map(item->item.getId()).collect(Collectors.toList()),
                            SettlementOwnerDetailEnum.InvoiceStatus.NO_INVOICE.getCode());
        }

        /**
         *   无需开票+否：未开票
         *   全部为否：未开票
         *   无需开票+是 ：部分开票
         *   无需开票+是+否 ：部分开票
         *   全部为是：已开票
         *   全部为无需开票：无需开票
         */
        if(list1.isEmpty()){
            if (list2.isEmpty()){
                if (list3.isEmpty()) {
                    settlementOwner.setInvoiceStatus(settlementOwner.getInvoiceStatus());
                }
                else {
                    settlementOwner.setInvoiceStatus(SettlementOwnerEnum.InvoiceStatus.INVOICED.getCode());
                }
            }
            else {
                if (list3.isEmpty()) {
                    settlementOwner.setInvoiceStatus(SettlementOwnerEnum.InvoiceStatus.NOT_INVOICE.getCode());
                }
                else {
                    settlementOwner.setInvoiceStatus(SettlementOwnerEnum.InvoiceStatus.PART_INVOICE.getCode());
                }
            }
        }else{
            if (list2.isEmpty()){
                if (list3.isEmpty()) {
                    settlementOwner.setInvoiceStatus(SettlementOwnerEnum.InvoiceStatus.NO_NEED_INVOICE.getCode());
                }
                else {
                    settlementOwner.setInvoiceStatus(SettlementOwnerEnum.InvoiceStatus.PART_INVOICE.getCode());
                }
            }
            else {
                if (list3.isEmpty()) {
                    settlementOwner.setInvoiceStatus(SettlementOwnerEnum.InvoiceStatus.NOT_INVOICE.getCode());
                }
                else {
                    settlementOwner.setInvoiceStatus(SettlementOwnerEnum.InvoiceStatus.PART_INVOICE.getCode());
                }
            }
        }
        settlementOwnerDao.updateInvoiceStatus(settlementOwner);

    }

    @Override
    public void settlementDriverConfirm(SettlementDriverConfirmMqParam mq) {

        OrderChild orderChild = orderChildDao.getByChildNo(mq.getChildNo()).orElseThrow(ResultEnum.DATA_NOT_FIND);
        if (orderChild.getConfirmTime() == null) {return;}

        OrderGoods orderGoods = orderGoodsDao
                .getByOrderGoodsNo(orderChild.getOrderGoodsNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        SettlementDriver settlementDriver = settlementDriverDao.findByChildNo(orderChild.getChildNo()).orNull();
        if (settlementDriver == null
                || !Objects.equals(settlementDriver.getStatus(), SettlementDriverEnum.Status.DRIVER_UNCONFIRMED.getCode())
        ) {
            return;
        }

        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao
                .getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        //车主结算单自动支付
        log.info(" 运单号 {}, 是否是普通单 {} ",settlementDriverDetail.getChildNo(),settlementDriverDetail.getInvoiceType());
        if (!settlementDriverDetail.getInvoiceType().equals(SettlementOwnerEnum.InvoiceType.ONLINE.getCode())) {
            paySettlementDriver(settlementDriverDetail);
        } else {
            if (Objects.equals(orderGoods.getPlatformFreightQuotationTaxType(),
                    QuotationEnum.PlatformFreightQuotationTaxType.NO.getCode())
                    && Objects.equals(orderGoods.getSettlementWay(), SettlementWayEnum.WayType.UNLOAD_LOSS.getCode())) {
                //插入同步网络货运待支付记录
                childSyncTransportRecordService.addOrderChildSyncTransportRecord(settlementDriverDetail);
            }
            else if (settlementDriverDetail.getPrepayFreightFlag().equals(SettlementDriverEnum.PrepayFreightFlag.PAYED.getCode())
                    && settlementDriverDetail.getPrepayFreight().compareTo(BigDecimal.ZERO) > 0) {
                //插入同步网络货运待支付记录
                childSyncTransportRecordService.addOrderChildSyncTransportRecord(settlementDriverDetail);
            }

        }

        settlementDriver.setStatus(SettlementDriverEnum.Status.WAIT_SETTLEMENT.getCode());
        settlementDriverDao.updateSettleStatus(settlementDriver);

        if (!Objects.equals(settlementDriver.getInvoiceType(), SettlementOwnerEnum.InvoiceType.ONLINE.getCode())){
            return;
        }

        // 发送mq (运单司机支付)
        orderChildBrokerMqService.orderChildDriverPay(orderChild.getChildNo());

    }

    private BigDecimal invoiceFreightCalc(Integer settlementWay, BigDecimal invoiceServiceFeeRate, SettlementOwnerDetail settlementOwnerDetail) {
        if (Objects.equals(settlementWay, SettlementWayEnum.WayType.LOAD.getCode())) { //订单结算方式为“装车净重”时，开票金额=实际净重*平台运费报价-货损金额。
            return settlementOwnerDetail.getWeight().multiply(settlementOwnerDetail.getFreightPrice())
                    .subtract(settlementOwnerDetail.getLossFreight());
        }
        else if (Objects.equals(settlementWay, SettlementWayEnum.WayType.UNLOAD_LOSS.getCode())) {
            if (invoiceServiceFeeRate!=null){
                //结算方式为“卸车净重（减货损）”，平台运费报价为“未税”时，开票金额=平台运费单价*实际净重-货损单价*货损吨数+开票服务费。
                return settlementOwnerDetail.getWeight().multiply(settlementOwnerDetail.getFreightPrice())
                        .subtract(settlementOwnerDetail.getLossPrice())
                        .add(settlementOwnerDetail.getInvoiceServiceFee());
            }
            else{
                //结算方式为“卸车净重（减货损）”，平台运费报价为“含税”时   开票金额=平台运费单价*实际净重-货损单价*货损吨数
                return settlementOwnerDetail.getWeight().multiply(settlementOwnerDetail.getFreightPrice())
                        .subtract(settlementOwnerDetail.getLossFreight());
            }
        }
        else { //订单结算方式为“卸车净重”时，开票金额=实际净重*平台运费报价。
            return settlementOwnerDetail.getWeight().multiply(settlementOwnerDetail.getFreightPrice());
        }
    }

}
