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

import cn.hutool.json.JSONUtil;
import com.clx.order.vo.feign.FeignOrderInfoVO;
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.*;
import com.clx.performance.dto.InvoicingStatusNotifyDTO;
import com.clx.performance.dto.PayStatusNotifyDTO;
import com.clx.performance.enums.*;
import com.clx.performance.enums.settle.*;
import com.clx.performance.extranal.broker.BrokerService;
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.OrderChildSyncTransportInvoiceRecord;
import com.clx.performance.model.OrderGoods;
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.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.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.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

@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;

    @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);
        SettlementDriverDetail settlementDriverDetail = settlementDriverDetailDao.getByChildNo(mq.getChildNo()).orElseThrow(PerformanceResultEnum.DATA_NOT_FIND);

        log.info("当前车主计费信息{},司机计费信息：{}", JSONUtil.parse(settlementOwnerDetail), JSONUtil.parse(settlementDriverDetail));
        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();
            }
        }

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

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

    @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());
    }

    @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;
        }

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

            Integer invoiceType;
            if (Objects.equals(result.getRiskStatus(), 1) || Objects.equals(result.getRiskStatus(), 2)) {
                invoiceType = SettlementOwnerEnum.InvoiceType.ORDINARY.getCode();
            } else if (Objects.equals(result.getSyncStatus(), 2)) {
                invoiceType = SettlementOwnerEnum.InvoiceType.ORDINARY.getCode();
            } else if (Objects.equals(result.getSyncStatus(), 0)) {
                OrderChildSyncTransportInvoiceRecord entity = new OrderChildSyncTransportInvoiceRecord();
                entity.setChildNo(orderChild.getChildNo());
                entity.setType(TransportSyncTypeEnum.Type.EXCEPTION.getCode());
                entity.setRemark("处理中");
                orderChildSyncTransportInvoiceRecordDao.saveEntity(entity);
                return;
            } else {
                invoiceType = SettlementOwnerEnum.InvoiceType.ONLINE.getCode();
            }

            // 发送mq （结算）
            settlementMqService.settle(orderChild.getChildNo(), invoiceType);
        }catch (Exception e){
            OrderChildSyncTransportInvoiceRecord entity = new OrderChildSyncTransportInvoiceRecord();
            entity.setChildNo(orderChild.getChildNo());
            entity.setType(TransportSyncTypeEnum.Type.EXCEPTION.getCode());
            entity.setRemark("接口调用失败");
            orderChildSyncTransportInvoiceRecordDao.saveEntity(entity);
        }
    }

    @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;
        }

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

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

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

    @Override
    public void payStatusSync(SettlementPayStatusSyncMqParam 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;
        }

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

        if (Objects.equals(result.getSettleStatus(), 1) ) {
            PayStatusNotifyDTO payStatusNotifyDTO = new PayStatusNotifyDTO();
            payStatusNotifyDTO.setChildNo(mq.getChildNo());
            orderChildSyncTransportRecordService.updateStatus(payStatusNotifyDTO);
        }
    }

    @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);
        }
        log.info("更新网络标识 {} ",orderChild.getChildNo());
        // 更新网络标识
        settlementService.updateSettlementDetailInvoiceType(settlementOwnerDetail.getChildNo(), SettlementOwnerEnum.InvoiceType.ORDINARY.getCode());
    }

    private void settlementDriverSave(SettlementDriverDetail detail,String settlementNo){
        SettlementDriver settlementDriver = new SettlementDriver();
        settlementDriver.setDriverUserNo(detail.getDriverUserNo());
        settlementDriver.setDriverName(detail.getDriverName());
        settlementDriver.setSettlementNo(settlementNo);
        settlementDriver.setChildNo(detail.getChildNo());
        settlementDriver.setOrderGoodsNo(detail.getOrderGoodsNo());
        settlementDriver.setOrderNo(detail.getOrderNo());
        settlementDriver.setGoodsId(detail.getGoodsId());
        settlementDriver.setGoodsName(detail.getGoodsName());
        settlementDriver.setTruckNo(detail.getTruckNo());
        settlementDriver.setFreightPrice(detail.getFreightPrice());
        settlementDriver.setWeight(detail.getWeight());
        settlementDriver.setFreight(detail.getFreight());
        settlementDriver.setLossPrice(detail.getLossPrice());
        settlementDriver.setLossWeight(detail.getLossWeight());
        settlementDriver.setLoanFlag(detail.getLoanFlag());
        settlementDriver.setLossFreight(detail.getLossFreight());
        settlementDriver.setPrepayFreightFlag(detail.getPrepayFreightFlag());
        settlementDriver.setSettlementFreight(detail.getSettlementFreight());
        settlementDriver.setInvoiceType(detail.getInvoiceType());
        settlementDriver.setSettlementPlatform(detail.getInvoiceType() == 1 ?
                        String.valueOf(SettlementPlatformEnum.Platform.WY.getCode()):
                String.valueOf(SettlementPlatformEnum.Platform.MSL.getCode()));
        if (settlementDriver.getInvoiceType().equals(SettlementOwnerEnum.InvoiceType.ONLINE.getCode())) {
            settlementDriver.setStatus(SettlementDriverEnum.Status.SETTLED.getCode());
        } else {
            settlementDriver.setStatus(SettlementDriverEnum.Status.WAIT_SETTLEMENT.getCode());
        }



        settlementDriverDao.saveEntity(settlementDriver);
    }

    @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, "系统");
        }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());
        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());

        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()));
        });

        settlementOwnerDao.updateSettlementPeriodMonth(settlementOwner);
    }


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

    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());
        }
    }

}
