package com.sckw.contract.dubbo;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Sets;
import com.sckw.contract.api.RemoteContractService;
import com.sckw.contract.api.model.dto.req.ContractAuditPara;
import com.sckw.contract.api.model.dto.res.*;
import com.sckw.contract.api.model.vo.*;
import com.sckw.contract.dao.*;
import com.sckw.contract.model.dto.res.QueryContractValidCountResDto;
import com.sckw.contract.model.entity.*;
import com.sckw.contract.model.vo.req.ContractDetailReq;
import com.sckw.contract.model.vo.res.ContractDetailResp;
import com.sckw.contract.model.vo.res.QueryLogisticDetailResp;
import com.sckw.contract.repository.*;
import com.sckw.contract.service.KwcContractLogisticsUnitService;
import com.sckw.contract.service.operateService.KwcContractLogisticsService;
import com.sckw.contract.service.operateService.KwcContractTradeService;
import com.sckw.core.common.enums.enums.ErrorCodeEnum;
import com.sckw.core.exception.BusinessException;
import com.sckw.core.exception.BusinessPlatfromException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.ContractStatusEnum;
import com.sckw.core.model.enums.CooperateTypeEnum;
import com.sckw.core.model.enums.EntTypeEnum;
import com.sckw.core.model.enums.SigningWayEnum;
import com.sckw.core.utils.BeanUtils;
import com.sckw.core.utils.CollectionUtils;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.redis.constant.RedisConstant;
import com.sckw.system.api.RemoteSystemService;
import com.sckw.transport.api.dubbo.TransportRemoteService;
import com.sckw.transport.api.model.vo.LogisticContractVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

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

/**
 * @author czh
 * @desc 合同远程接口实现
 * @date 2023/7/31
 */
@DubboService(group = "design", version = "1.0.0")
@RequiredArgsConstructor
@Slf4j
public class RemoteContractServiceImpl implements RemoteContractService {

    @Autowired
    private KwcContractLogisticsMapper kwcContractLogisticsMapper;

    @Autowired
    private KwcContractLogisticsUnitMapper kwcContractLogisticsUnitMapper;

    @Autowired
    private KwcContractLogisticsUnitService kwcContractLogisticsUnitService;

    @Autowired
    private KwcContractTradeMapper kwcContractTradeMapper;
    @Autowired
    private KwcContractTradeGoodsMapper kwcContractTradeGoodsMapper;
    @Autowired
    private KwcContractTradeUnitMapper kwcContractTradeUnitMapper;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    private RemoteSystemService remoteSystemService;
    @DubboReference(version = "1.0.0", group = "design", check = false, timeout = 8000)
    private TransportRemoteService transportRemoteService;
    private final RedisTemplate<String, Object> redisTemplate;

    private final KwcContractTradeRepository kwcContractTradeRepository;
    private final KwcContractLogisticsRepository contractLogisticsRepository;
    private final KwcContractTradeUnitRepository kwcContractTradeUnitRepository;
    private final KwcContractTradeGoodsRepository kwcContractTradeGoodsRepository;
    private final KwcContractLogisticsUnitRepository kwcContractLogisticsUnitRepository;
    private final KwcContractLogisticsGoodsRepository kwcContractLogisticsGoodsRepository;
    private final KwcContractTradeService kwcContractTradeService;
    private final KwcContractLogisticsScoreRepository contractLogisticsScoreRepository;
    private final KwcContractLogisticsService kwcContractLogisticsService;

    @Override
    public Map<Long, ContractCommonInfoResDto> queryContractBaseInfo(List<Long> contractIds) {
        HashMap<Long, ContractCommonInfoResDto> map = new HashMap<>(4);
        for (Long contractId : contractIds) {
            KwcContractLogistics kwcContractLogistics = kwcContractLogisticsMapper.selectById(contractId);
            if (Objects.nonNull(kwcContractLogistics)) {
                Integer status = kwcContractLogistics.getStatus();
                Integer delFlag = kwcContractLogistics.getDelFlag();
                if (Objects.equals(status, ContractStatusEnum.SAVE.getCode()) || delFlag.equals(Global.YES)) {
                    continue;
                }
                map.put(contractId, fillContractLogistics(kwcContractLogistics));
                continue;
            }

            KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(contractId);
            if (Objects.nonNull(kwcContractTrade)) {
                Integer status = kwcContractTrade.getStatus();
                Integer delFlag = kwcContractTrade.getDelFlag();
                if (Objects.equals(status, ContractStatusEnum.SAVE.getCode()) || delFlag.equals(Global.YES)) {
                    continue;
                }
                map.put(contractId, fillContractTrade(kwcContractTrade));
            }
        }
        return map;
    }


    /**
     * @param contractId 合同id  performedAmount履约量
     * @desc: 更新已履约量
     * @author: czh
     * @date: 2023/8/31
     */
    @Override
    public void updatePerformed(Long contractId, BigDecimal performedAmount) {
        KwcContractLogistics kwcContractLogistics = kwcContractLogisticsMapper.selectById(contractId);
        if (Objects.nonNull(kwcContractLogistics)) {
            if (kwcContractLogistics.getStatus().equals(ContractStatusEnum.COMPLETE.getCode())) {
                return;
            }
            kwcContractLogistics.setPerformedAmount(kwcContractLogistics.getPerformedAmount().add(performedAmount));
            kwcContractLogisticsMapper.updateById(kwcContractLogistics);
            return;
        }

        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(contractId);
        if (Objects.nonNull(kwcContractTrade)) {
            if (kwcContractTrade.getStatus().equals(ContractStatusEnum.COMPLETE.getCode())) {
                return;
            }
            kwcContractTrade.setPerformedAmount(kwcContractTrade.getPerformedAmount().add(performedAmount));
            kwcContractTradeMapper.updateById(kwcContractTrade);
        }
    }


    /**
     * @param entId 企业id
     * @return Map<Integer, Integer>
     * @desc: 根据企业id统计企业下的有效合同个数
     * @author: czh
     * @date: 2023/9/8
     */
    @Override
    public Map<Integer, Integer> queryContractValidCount(Long entId, List<Long> enterpriseIds) {
        List<Long> entIdList = new ArrayList<>();
        //原来的
//        if (Objects.nonNull(entId)) {
//            EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(entId);
//            if (Objects.isNull(entCacheResDto)) {
//                return Collections.emptyMap();
//            }
//            entIdList.add(entId);
//            List<EntCacheResDto> child = entCacheResDto.getChild();
//            if (CollectionUtils.isNotEmpty(child)) {
//                entIdList.addAll(child.stream().map(EntCacheResDto::getId).toList());
//            }
//        }

        //加客户经理数据过滤
        enterpriseIds.add(entId);
        enterpriseIds = enterpriseIds.stream().distinct().collect(Collectors.toList());
        entIdList.addAll(enterpriseIds);
//        if (Objects.nonNull(enterpriseIds) && enterpriseIds.size() > 0) {
//            for (Long aLong : entIdList) {
//                EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(aLong);
//                if (Objects.isNull(entCacheResDto)) {
//                    return Collections.emptyMap();
//                }
//                entIdList.add(aLong);
//                List<EntCacheResDto> child = entCacheResDto.getChild();
//                if (CollectionUtils.isNotEmpty(child)) {
//                    entIdList.addAll(child.stream().map(EntCacheResDto::getId).toList());
//                }
//            }
//        }

        List<QueryContractValidCountResDto> queryContractValidCountResDtos = kwcContractTradeMapper.queryContractValidCount(entIdList);
        if (CollectionUtils.isEmpty(queryContractValidCountResDtos)) {
            return Collections.emptyMap();
        }

        return queryContractValidCountResDtos.stream().collect(Collectors.toMap(QueryContractValidCountResDto::getUnitType, QueryContractValidCountResDto::getCnt, (o, n) -> n));
    }

    /**
     * @param contractNo 合同编号
     * @param acceptId   承运企业id
     * @param consignId  托运企业id
     * @return
     */
    @Override
    public ContractLogisticsOrderResDto getContractByContractNo(String contractNo, Long acceptId, Long consignId) {
        ContractLogisticsOrderResDto logisticsOrderResDto = new ContractLogisticsOrderResDto();
        List<KwcContractLogistics> list = kwcContractLogisticsMapper.selectIsSole(contractNo, acceptId, consignId);
        if (list.size() > 0) {
            KwcContractLogistics contractLogistics = list.get(0);
            logisticsOrderResDto.setId(contractLogistics.getId());
            logisticsOrderResDto.setContactName(contractLogistics.getName());
            logisticsOrderResDto.setContractNo(contractLogistics.getContractNo());
            logisticsOrderResDto.setSigningWay(contractLogistics.getSigningWay());
            logisticsOrderResDto.setSigningWayName(Objects.requireNonNull(SigningWayEnum.getName(contractLogistics.getSigningWay())).getName());
            logisticsOrderResDto.setStatus(contractLogistics.getStatus());
            logisticsOrderResDto.setStatusName((Objects.requireNonNull(ContractStatusEnum.getName(contractLogistics.getStatus())).getName()));
            List<KwcContractLogisticsUnit> kwcContractLogisticsUnits = kwcContractLogisticsUnitService.queryByContractId(contractLogistics.getId());
            if (CollectionUtils.isNotEmpty(kwcContractLogisticsUnits)) {
                for (KwcContractLogisticsUnit kwcContractLogisticsUnit : kwcContractLogisticsUnits) {
                    if (kwcContractLogisticsUnit.getUnitType().equals(CooperateTypeEnum.CONSIGN.getCode())) {
                        logisticsOrderResDto.setConsignEntId(kwcContractLogisticsUnit.getEntId());
                        logisticsOrderResDto.setConsignEntName(kwcContractLogisticsUnit.getFirmName());
                    }
                    if (kwcContractLogisticsUnit.getUnitType().equals(CooperateTypeEnum.CARRIAGE.getCode())) {
                        logisticsOrderResDto.setAcceptCarriageEntId(kwcContractLogisticsUnit.getEntId());
                        logisticsOrderResDto.setAcceptCarriageEntName(kwcContractLogisticsUnit.getFirmName());
                    }
                }
            }
        }
        return logisticsOrderResDto;
    }

    @Override
    public ContractLogisticsAndTradeOrderResDto queryContractByContractId(Long tradeOrderContractId, Long tradeId) {
        //根据贸易合同查询贸易合同
        KwcContractTrade kwcContractTrade = kwcContractTradeRepository.queryByContractId(tradeOrderContractId);
        if (Objects.isNull(kwcContractTrade)) {
            return new ContractLogisticsAndTradeOrderResDto();
        }
        ContractLogisticsAndTradeOrderResDto contractLogisticsAndTradeOrderResDto = new ContractLogisticsAndTradeOrderResDto();
        contractLogisticsAndTradeOrderResDto.setId(kwcContractTrade.getId());
        contractLogisticsAndTradeOrderResDto.setContactName(kwcContractTrade.getName());
        contractLogisticsAndTradeOrderResDto.setContractNo(kwcContractTrade.getContractNo());
        //根据贸易订单id查询物流订单和物流合同关联信息
        List<LogisticContractVo> logisticContractVos = transportRemoteService.queryLogisticContractByTradeId(tradeId);
        Set<Long> logContractIds = Sets.newHashSet();
        if (CollectionUtils.isNotEmpty(logisticContractVos)) {
            logContractIds =
                    logisticContractVos.stream().map(LogisticContractVo::getLogContractId).collect(Collectors.toSet());
        }
        //查询物流合同
        List<KwcContractLogistics> contractLogistics = contractLogisticsRepository.queryByLogisticContractIds(logContractIds);
        if (CollectionUtils.isNotEmpty(contractLogistics)) {
            List<ContractLogisticsAndTradeOrderResDto.ContractLogisticsOrder> contractLogisticsOrders = contractLogistics.stream().map(c -> {
                ContractLogisticsAndTradeOrderResDto.ContractLogisticsOrder contractLogisticsOrder = new ContractLogisticsAndTradeOrderResDto.ContractLogisticsOrder();
                contractLogisticsOrder.setLogisticsContractId(c.getId());
                contractLogisticsOrder.setLogisticsContractName(c.getName());
                contractLogisticsOrder.setLogisticsContractNo(c.getContractNo());
                return contractLogisticsOrder;
            }).collect(Collectors.toList());
            contractLogisticsAndTradeOrderResDto.setLogisticsContracts(contractLogisticsOrders);
        }

        return contractLogisticsAndTradeOrderResDto;
    }

    @Override
    public TradeContractResDto queryTradeContract(Long tradeContractId, Long goodsId) {
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(tradeContractId);
        if (Objects.nonNull(kwcContractTrade)) {
            TradeContractResDto tradeContractResDto = BeanUtils.toBean(kwcContractTrade, TradeContractResDto.class);
            tradeContractResDto.setId(kwcContractTrade.getId());
            tradeContractResDto.setContactName(kwcContractTrade.getName());
            tradeContractResDto.setContractNo(kwcContractTrade.getContractNo());
            tradeContractResDto.setDispatchWay(kwcContractTrade.getDispatchWay());
            tradeContractResDto.setMeasurementWay(kwcContractTrade.getMeasurementWay());
            KwcContractTradeGoods kwcContractTradeGoods = kwcContractTradeGoodsMapper.selectOne(new LambdaQueryWrapper<KwcContractTradeGoods>()
                    .eq(KwcContractTradeGoods::getContractId, tradeContractId)
                    .eq(KwcContractTradeGoods::getGoodsId, goodsId)
                    .eq(KwcContractTradeGoods::getDelFlag, 0)
            );
            Optional.ofNullable(kwcContractTradeGoods).ifPresent(d -> tradeContractResDto.setGoodsInfoDto(BeanUtils.toBean(d, GoodsInfoDto.class)));

            List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitMapper.selectList(new LambdaQueryWrapper<KwcContractTradeUnit>().eq(KwcContractTradeUnit::getContractId, tradeContractId)
                    .eq(KwcContractTradeUnit::getDelFlag, 0));
            Optional.ofNullable(kwcContractTradeUnits).ifPresent(d -> tradeContractResDto.setUnitList(d.stream().map(t -> BeanUtils.toBean(t, TradeContractUnitDto.class)).toList()));

            return tradeContractResDto;
        }
        return null;
    }

    @Override
    public TradeContractGoodsDto queryTradeContractNew(Long entId, Long goodsId, LocalDateTime time) {
        return kwcContractTradeMapper.queryNewSignPrice(entId, goodsId, time);
    }

    @Override
    public List<Long> queryNewSignGoods(Long entId, LocalDateTime time) {
        return kwcContractTradeMapper.queryNewSignGoods(entId, time);
    }

    @Override
    public List<Long> querySignTradeContract(Long entId, LocalDateTime time) {
        return kwcContractTradeMapper.querySignTradeContract(entId, time);
    }

    @Override
    public List<ContractLogisticsOrderResDto> queryContractLogisticsOrder(LogisticsOrderDto logisticsOrderDto) {
        log.info("查询物流合同请求：{}", JSON.toJSONString(logisticsOrderDto));
        return kwcContractTradeService.queryContractLogisticsOrder(logisticsOrderDto);

    }


    @Override
    public List<ContractTradeOrderInfo> queryContractTradeOrder(ContractTradeOrderDto contractTradeOrderDto) {
        log.info("查询贸易合同订单，请求：{}", JSON.toJSONString(contractTradeOrderDto));
        return kwcContractTradeService.queryContractTradeOrder(contractTradeOrderDto);
    }

    @Override
    public List<Long> queryTradeContractInfo(Long contractId) {
        return kwcContractTradeService.queryTradeContractInfo(contractId);
    }

    @Override
    public KwcContractLogisticsDto queryContractByContractId(Long contractId) {
        KwcContractLogistics kwcContractTrade = kwcContractLogisticsMapper.selectById(contractId);
        if (Objects.nonNull(kwcContractTrade)) {
            KwcContractLogisticsDto tradeContractResDto = new KwcContractLogisticsDto();
            tradeContractResDto.setId(kwcContractTrade.getId());
            tradeContractResDto.setName(kwcContractTrade.getName());
            tradeContractResDto.setContractNo(kwcContractTrade.getContractNo());
            tradeContractResDto.setAllowedError(kwcContractTrade.getAllowedError());
            return tradeContractResDto;
        }
        return new KwcContractLogisticsDto();
    }

    @Override
    public List<TradeContractUnitDto> queryContractUnitByContractId(Long contractId) {
        List<KwcContractTradeUnit> units = kwcContractTradeUnitRepository.queryByContractId(contractId);
        if (org.apache.commons.collections4.CollectionUtils.isEmpty(units)) {
            return List.of();
        }
        return units.stream().map(unit -> {
            TradeContractUnitDto tradeContractUnitDto = new TradeContractUnitDto();
            tradeContractUnitDto.setUnitType(String.valueOf(unit.getUnitType()));
            tradeContractUnitDto.setEntId(unit.getEntId());
            tradeContractUnitDto.setFirmName(unit.getFirmName());
            tradeContractUnitDto.setContactsId(unit.getContractId());
            tradeContractUnitDto.setContacts(unit.getContacts());
            tradeContractUnitDto.setPhone(unit.getPhone());
            return tradeContractUnitDto;
        }).collect(Collectors.toList());
    }

    @Override
    public List<TradeContractUnitDto> queryLogContractUnitByContractId(Long contractId) {
        List<KwcContractLogisticsUnit> kwcContractLogisticsUnits = kwcContractLogisticsUnitRepository.queryByContractId(contractId);
        if(CollUtil.isEmpty(kwcContractLogisticsUnits)){
            return new ArrayList<>();
        }
        return kwcContractLogisticsUnits.stream().map(unit -> {
            TradeContractUnitDto tradeContractUnitDto = new TradeContractUnitDto();
            tradeContractUnitDto.setUnitType(String.valueOf(unit.getUnitType()));
            tradeContractUnitDto.setEntId(unit.getEntId());
            tradeContractUnitDto.setFirmName(unit.getFirmName());
            tradeContractUnitDto.setContactsId(unit.getContractId());
            tradeContractUnitDto.setContacts(unit.getContacts());
            tradeContractUnitDto.setPhone(unit.getPhone());
            return tradeContractUnitDto;
        }).collect(Collectors.toList());
    }


    private ContractCommonInfoResDto fillContractLogistics(KwcContractLogistics kwcContractLogistics) {
        ContractCommonInfoResDto contractCommonInfoResDto = new ContractCommonInfoResDto();
        List<EntInfo> entList = new ArrayList<>();
        contractCommonInfoResDto.setId(kwcContractLogistics.getId());
        contractCommonInfoResDto.setContactName(kwcContractLogistics.getName());
        contractCommonInfoResDto.setContractCode(kwcContractLogistics.getContractNo());
        contractCommonInfoResDto.setSigningWay(kwcContractLogistics.getSigningWay());
        contractCommonInfoResDto.setSigningWayName(Objects.requireNonNull(SigningWayEnum.getName(kwcContractLogistics.getSigningWay())).getName());
        contractCommonInfoResDto.setEntInfoList(entList);
        contractCommonInfoResDto.setStatus(kwcContractLogistics.getStatus());
        contractCommonInfoResDto.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(kwcContractLogistics.getStatus())).getName());
        contractCommonInfoResDto.setDispatchWay(kwcContractLogistics.getDispatchWay());
        contractCommonInfoResDto.setSettlement(kwcContractLogistics.getSettlement());
        List<KwcContractLogisticsUnit> kwcContractLogisticsUnits = kwcContractLogisticsUnitService.queryByContractId(kwcContractLogistics.getId());
        if (CollectionUtils.isNotEmpty(kwcContractLogisticsUnits)) {
            for (KwcContractLogisticsUnit kwcContractLogisticsUnit : kwcContractLogisticsUnits) {
                EntInfo entInfo = new EntInfo();
                entInfo.setEntId(kwcContractLogisticsUnit.getEntId());
                entInfo.setEntName(kwcContractLogisticsUnit.getFirmName());
                entList.add(entInfo);
            }
        }
        return contractCommonInfoResDto;
    }


    private ContractCommonInfoResDto fillContractTrade(KwcContractTrade kwcContractTrade) {
        List<EntInfo> entList = new ArrayList<>();
        ContractCommonInfoResDto contractCommonInfoResDto = new ContractCommonInfoResDto();
        contractCommonInfoResDto.setId(kwcContractTrade.getId());
        contractCommonInfoResDto.setContactName(kwcContractTrade.getName());
        contractCommonInfoResDto.setContractCode(kwcContractTrade.getContractNo());
        contractCommonInfoResDto.setSigningWay(kwcContractTrade.getSigningWay());
        contractCommonInfoResDto.setSigningWayName(Objects.requireNonNull(SigningWayEnum.getName(kwcContractTrade.getSigningWay())).getName());
        contractCommonInfoResDto.setEntInfoList(entList);
        contractCommonInfoResDto.setStatus(kwcContractTrade.getStatus());
        contractCommonInfoResDto.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(kwcContractTrade.getStatus())).getName());
        contractCommonInfoResDto.setDispatchWay(kwcContractTrade.getDispatchWay());
        contractCommonInfoResDto.setEntId(kwcContractTrade.getEntId());
        contractCommonInfoResDto.setSalesmanId(kwcContractTrade.getSalesmanId());
        List<KwcContractLogisticsUnit> kwcContractLogisticsUnits = kwcContractLogisticsUnitService.queryByContractId(kwcContractTrade.getId());
        if (CollectionUtils.isNotEmpty(kwcContractLogisticsUnits)) {
            for (KwcContractLogisticsUnit kwcContractLogisticsUnit : kwcContractLogisticsUnits) {
                EntInfo entInfo = new EntInfo();
                entInfo.setEntId(kwcContractLogisticsUnit.getEntId());
                entInfo.setEntName(kwcContractLogisticsUnit.getFirmName());
                entList.add(entInfo);
            }
        }
        return contractCommonInfoResDto;
    }

    @Override
    public List<LogisticsEntDtoVO> queryAutoContractLogOrder(Long entId, List<Long> goodsIds) {
        return kwcContractTradeService.queryAutoContractLogOrder(entId, goodsIds);
    }

    @Override
    public List<LogisticsEntDtoVO> queryContractLogOrder(Long entId, Long goodsId) {
        return kwcContractTradeService.queryContractLogOrder(entId, goodsId);
    }

    @Override
    public LogisticsGoodsDto queryLogGoodsByContractId(Long contractId, Long goodsId) {
        return kwcContractTradeService.queryLogGoodsByContractId(contractId, goodsId);
    }

    @Override
    public TradeContractUnitDto queryEntByContractId(Long contractId) {
        return kwcContractTradeService.queryEntByContractId(contractId);
    }

    @Override
    public ContractLogisticsScoreVO findLogisticsScoreByEntId(Long supEntId, Long entId) {
        KwcContractLogisticsScore contractLogisticsScore = kwcContractTradeService.queryEntScoreByEntId(supEntId, entId);
        if (contractLogisticsScore == null) {
            return new ContractLogisticsScoreVO();
        }

        ContractLogisticsScoreVO vo = new ContractLogisticsScoreVO();
        vo.setProviderEntId(contractLogisticsScore.getProviderEntId());
        vo.setLogisticsEntId(contractLogisticsScore.getLogisticsEntId());
        vo.setScore(contractLogisticsScore.getScore());
        return vo;
    }

    @Override
    public KwcContractLogisticsDto findLogContractByEntId(Long entId) {
        //查询物流企业合同信息
        List<KwcContractLogisticsUnit> contractLogisticsUnits = kwcContractLogisticsUnitRepository.queryByEntIdAndEntType(entId, EntTypeEnum.LOGISTICS4.getCode());
        if (CollectionUtils.isEmpty(contractLogisticsUnits)) {
            return null;
        }
        Set<Long> contractIds = contractLogisticsUnits.stream().map(KwcContractLogisticsUnit::getContractId).collect(Collectors.toSet());

        //查询自动派车且有效的物流合同
        List<KwcContractLogistics> kwcContractLogistics = contractLogisticsRepository.queryByIdsAndDispatch(contractIds);
        if (CollectionUtils.isEmpty(kwcContractLogistics)) {
            return null;
        }
        if (kwcContractLogistics.size() > 1) {
            throw new BusinessPlatfromException(ErrorCodeEnum.DATA_NOT_EXIST, "只能存在有且只有一条的自动派单有效的物流合同！");
        }

        return kwcContractLogistics.stream().findFirst().map(log -> {
            KwcContractLogisticsDto dto = new KwcContractLogisticsDto();
            dto.setId(log.getId());
            dto.setEntId(log.getEntId());
            dto.setContractNo(log.getContractNo());
            dto.setName(log.getName());
            dto.setSigningWay(log.getSigningWay());
            dto.setCharging(log.getCharging());
            dto.setTrading(log.getTrading());
            dto.setDispatchWay(log.getDispatchWay());
            dto.setStartTime(log.getStartTime());
            dto.setEndTime(log.getEndTime());
            dto.setAmount(log.getAmount());
            dto.setPerformedAmount(log.getPerformedAmount());
            dto.setSigningUrl(log.getSigningUrl());
            dto.setSignedUrl(log.getSignedUrl());
            dto.setSigningNo(log.getSigningNo());
            dto.setContractPid(log.getContractPid());
            dto.setRemark(log.getRemark());
            dto.setStatus(log.getStatus());
            dto.setBusinessId(log.getBusinessId());
            dto.setCommonPrice(log.getCommonPrice());

            //查询供应企业
            KwcContractLogisticsUnit unit = kwcContractLogisticsUnitRepository
                    .queryByContractIdAndEntType(log.getId(), EntTypeEnum.LOGISTICS3.getCode());
            if (unit != null) {
                dto.setSupEntId(unit.getEntId());
            }
            return dto;
        }).orElse(null);
    }

    @Override
    public TradeContractGoodsDto queryContractGoodsByContractId(Long contractId, Long goodsId) {
        KwcContractTradeGoods contractTradeGoods = kwcContractTradeGoodsRepository.queryByContractIdAndGoodsId(contractId, goodsId);
        if (Objects.isNull(contractTradeGoods)) {
            return new TradeContractGoodsDto();
        }
        TradeContractGoodsDto tradeContractGoodsDto = new TradeContractGoodsDto();
        tradeContractGoodsDto.setPrice(contractTradeGoods.getPrice());
        return tradeContractGoodsDto;

    }

    @Override
    public List<TradeContractGoodsDto> queryContractGoodsByContractIds(Set<Long> contractIds, Set<Long> goodsIds) {
        List<KwcContractTradeGoods> contractTradeGoods = kwcContractTradeGoodsRepository.queryByContractIdsAndGoodsIds(contractIds, goodsIds);
        if (Objects.isNull(contractTradeGoods)) {
            return List.of();
        }
        return contractTradeGoods.stream().map(contractTrade -> {
            TradeContractGoodsDto tradeContractGoodsDto = new TradeContractGoodsDto();
            tradeContractGoodsDto.setContractId(contractTrade.getContractId());
            tradeContractGoodsDto.setGoodsId(contractTrade.getGoodsId());
            tradeContractGoodsDto.setPrice(contractTrade.getPrice());
            return tradeContractGoodsDto;
        }).collect(Collectors.toList());
    }

    @Override
    public Long queryTradeCount(Long entId, Integer type) {
        return kwcContractTradeService.querySign(entId, type);
    }

    @Override
    public Long queryLogisticsCount(Long entId, Integer type) {
        // type 买方或物流方
        return kwcContractLogisticsMapper.selectSignCount(entId, type);
    }

    @Override
    public ContractCountVo contractCount() {
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        Long count = kwcContractTradeMapper.count(ids);
        ContractCountVo contractCountVo = new ContractCountVo();
        contractCountVo.setTradeContractCount(count);
        contractCountVo.setLogisticsContractCount(0L);
        Long count1 = kwcContractLogisticsMapper.count(ids, LoginUserHolder.getEntId());
        contractCountVo.setLogisticsContractCount(count1);
        return contractCountVo;
    }

    @Override
    public List<ContractVo> tradeList() {
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        return kwcContractTradeMapper.tradeList(ids, false, false);
    }

    @Override
    public List<ContractVo> logisticsList() {
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }

        return kwcContractLogisticsMapper.logisticsList(ids, false, LoginUserHolder.getEntId());
    }

    private List<Long> separateAndRotate(List<Long> list, long pivot) {
        if (list == null || list.isEmpty()) {
            return new ArrayList<>();
        }

        // 查找分隔元素的索引
        int pivotIndex = list.indexOf(pivot);
        if (pivotIndex == -1) {
            // 如果元素不存在，返回原列表的副本
            return new ArrayList<>(list);
        }

        List<Long> result = new ArrayList<>();

        // 添加右边的元素（分隔元素之后的部分）
        for (int i = pivotIndex + 1; i < list.size(); i++) {
            result.add(list.get(i));
        }

        // 添加左边的元素（分隔元素之前的部分）
        for (int i = 0; i < pivotIndex; i++) {
            result.add(list.get(i));
        }
        return result;
    }

    @Override
    public ContractDetailRespVo auditTradeContract(ContractAuditPara contractAuditPara) {
        Long contractId = contractAuditPara.getContractId();
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        String key = String.format(RedisConstant.AUDIT_TRADE_CONTRACT, LoginUserHolder.getEntId());

        if (contractAuditPara.getStart()) {//首次加载，合同id为第一个合同
            if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
                redisTemplate.delete(key);
            }
            //写入缓存
            List<ContractVo> contractVos = kwcContractTradeMapper.tradeList(ids, true, true);
            if (CollUtil.isNotEmpty(contractVos)) {
                List<Long> list = contractVos.stream().map(ContractVo::getId).toList();
                List<Long> longs = separateAndRotate(list, contractId);
                redisTemplate.opsForList().rightPushAll(key, longs);
                redisTemplate.expire(key, 24, TimeUnit.HOURS);
            }

        } else {
            contractId = (Long) redisTemplate.opsForList().leftPop(key);
            if (Objects.isNull(contractId)) {
                throw new BusinessException("已审核完成");
            }
        }

        ContractDetailReq contractDetailReq = new ContractDetailReq();
        contractDetailReq.setContractId(String.valueOf(contractId));
        ContractDetailResp contractDetailResp = kwcContractTradeService.queryContractDetail(contractDetailReq);
        if (Objects.nonNull(contractDetailResp)) {
            return BeanUtil.toBean(contractDetailResp, ContractDetailRespVo.class);
        }
        throw new BusinessException("未找到合同");
    }

    @Override
    public ContractDetailRespVo signTradeContract(ContractAuditPara contractAuditPara) {
        Long contractId = contractAuditPara.getContractId();
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        String key = String.format(RedisConstant.SIGN_TRADE_CONTRACT, LoginUserHolder.getEntId());

        if (contractAuditPara.getStart()) {//首次加载，合同id为第一个合同
            if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
                redisTemplate.delete(key);
            }
            //写入缓存
            List<ContractVo> contractVos = kwcContractTradeMapper.tradeList(ids, false, true);
            if (CollUtil.isNotEmpty(contractVos)) {
                List<Long> list = contractVos.stream().map(ContractVo::getId).toList();
                List<Long> longs = separateAndRotate(list, contractId);
                redisTemplate.opsForList().rightPushAll(key, longs);
                redisTemplate.expire(key, 24, TimeUnit.HOURS);
            }

        } else {
            contractId = (Long) redisTemplate.opsForList().leftPop(key);
            if (Objects.isNull(contractId)) {
                throw new BusinessException("已审核完成");
            }
        }

        ContractDetailReq contractDetailReq = new ContractDetailReq();
        contractDetailReq.setContractId(String.valueOf(contractId));
        ContractDetailResp contractDetailResp = kwcContractTradeService.queryContractDetail(contractDetailReq);
        if (Objects.nonNull(contractDetailResp)) {
            return BeanUtil.toBean(contractDetailResp, ContractDetailRespVo.class);
        }
        throw new BusinessException("未找到合同");
    }

    @Override
    public LogisticDetailRespVo signLogisticsContract(ContractAuditPara contractAuditPara) {
        Long contractId = contractAuditPara.getContractId();
        List<Long> ids = new ArrayList<>();
        if (!LoginUserHolder.isManager()) {
            ids = LoginUserHolder.getChildEntList();
        }
        String key = String.format(RedisConstant.SIGN_LOGISTICS_CONTRACT, LoginUserHolder.getEntId());

        if (contractAuditPara.getStart()) {//首次加载，合同id为第一个合同
            if (Boolean.TRUE.equals(redisTemplate.hasKey(key))) {
                redisTemplate.delete(key);
            }
            //写入缓存
            List<ContractVo> contractVos = kwcContractLogisticsMapper.logisticsList(ids, true, LoginUserHolder.getEntId());
            if (CollUtil.isNotEmpty(contractVos)) {
                List<Long> list = contractVos.stream().map(ContractVo::getId).toList();
                List<Long> longs = separateAndRotate(list, contractId);
                redisTemplate.opsForList().rightPushAll(key, longs);
                redisTemplate.expire(key, 24, TimeUnit.HOURS);
            }

        } else {
            contractId = (Long) redisTemplate.opsForList().leftPop(key);
            if (Objects.isNull(contractId)) {
                throw new BusinessException("已审核完成");
            }
        }

        ContractDetailReq contractDetailReq = new ContractDetailReq();
        contractDetailReq.setContractId(String.valueOf(contractId));
        QueryLogisticDetailResp queryLogisticDetailResp = kwcContractLogisticsService.queryLogisticsContractDetail(contractDetailReq);
        if (Objects.nonNull(queryLogisticDetailResp)) {
            return BeanUtil.toBean(queryLogisticDetailResp, LogisticDetailRespVo.class);
        }
        throw new BusinessException("未找到合同");
    }

    @Override
    public void updateTradeContractGoodsPerformed(Long contractId, Long goodsId, BigDecimal orderAmount) {
        KwcContractTradeGoods tradeGoods = kwcContractTradeGoodsMapper.selectOne(new LambdaQueryWrapper<KwcContractTradeGoods>()
                .eq(KwcContractTradeGoods::getContractId, contractId)
                .eq(KwcContractTradeGoods::getGoodsId, goodsId)
                .eq(KwcContractTradeGoods::getDelFlag, 0)
        );
        if (Objects.isNull(tradeGoods)) {
            throw new BusinessException("贸易合同商品信息不存在");
        }
        BigDecimal performed = tradeGoods.getPerformedAmount() != null ? tradeGoods.getPerformedAmount() : BigDecimal.ZERO;
        tradeGoods.setPerformedAmount(performed.add(orderAmount));
        tradeGoods.setUpdateTime(new Date());
        kwcContractTradeGoodsMapper.updateById(tradeGoods);
    }

}
