package com.sckw.contract.service;

import java.io.IOException;
import java.util.Date;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.sckw.contract.model.dto.req.QueryListReqDto;
import com.sckw.contract.model.dto.res.QueryListResDto;
import com.sckw.contract.model.entity.*;
import com.sckw.contract.model.report.LogisticsListExport;
import com.sckw.contract.model.report.TradeListExport;
import com.sckw.contract.model.vo.req.*;

import com.sckw.contract.model.vo.res.*;
import com.sckw.core.common.enums.enums.DictEnum;
import com.sckw.core.common.enums.enums.DictTypeEnum;
import com.sckw.core.exception.SystemException;
import com.sckw.core.model.constant.Global;
import com.sckw.core.model.enums.ContractStatusEnum;
import com.sckw.core.model.enums.ContractTrackEnum;
import com.sckw.core.model.enums.CooperateTypeEnum;
import com.sckw.core.model.enums.EntTypeEnum;
import com.sckw.core.model.page.PageHelperUtil;
import com.sckw.core.model.page.PageResult;
import com.sckw.core.utils.*;
import com.sckw.core.web.constant.HttpStatus;
import com.sckw.core.web.context.LoginUserHolder;
import com.sckw.excel.utils.EasyExcelUtil;
import com.sckw.excel.utils.ExcelUtil;
import com.sckw.order.api.dubbo.TradeOrderInfoService;
import com.sckw.order.api.model.ContractSignCompletedParam;
import com.sckw.product.api.dubbo.GoodsInfoService;
import com.sckw.product.api.model.KwpGoods;
import com.sckw.stream.enums.MessageEnum;
import com.sckw.stream.model.UserInfo;
import com.sckw.system.api.model.dto.res.EntCacheResDto;
import com.sckw.system.api.model.dto.res.SysDictResDto;
import com.sckw.system.api.model.dto.res.UserCacheResDto;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sckw.system.api.RemoteSystemService;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import com.sckw.contract.dao.KwcContractTradeMapper;

/**
 * @author PC
 * @description 针对表【kwc_contract_trade(交易合同（采购合同/销售合同）)】的数据库操作Service实现
 * @createDate 2023-07-13 13:36:19
 */
@Service
@Slf4j
public class KwcContractTradeService {


    @Autowired
    private KwcContractTradeMapper kwcContractTradeMapper;

    @Autowired
    private KwcContractTradeGoodsService kwcContractTradeGoodsService;

    @Autowired
    private KwcContractTradeTrackService kwcContractTradeTrackService;

    @Autowired
    private KwcContractTradeUnitService kwcContractTradeUnitService;

    @Autowired
    private CommonBusinessService commonBusinessService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private RemoteSystemService remoteSystemService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private GoodsInfoService goodsInfoService;

    @DubboReference(version = "1.0.0", group = "design", check = false)
    private TradeOrderInfoService tradeOrderInfoService;

    /**销售合同*/
    @Value(value = "${jumpUrl.saleSendContract}")
    private String saleSendContract;

    /**采购合同*/
    @Value(value = "${jumpUrl.purchaseSendContract}")
    private String purchaseSendContract;

    /**托运合同*/
    @Value(value = "${jumpUrl.consignmentSendContract}")
    private String consignmentSendContract;

    /**承运合同*/
    @Value(value = "${jumpUrl.acceptanceSendContract}")
    private String acceptanceSendContract;

    /**app销售合同*/
    @Value(value = "${jumpUrl.appSaleSendContract}")
    private String appSaleSendContract;

    /**app采购合同*/
    @Value(value = "${jumpUrl.appPurchaseSendContract}")
    private String appPurchaseSendContract;

    /**app托运合同*/
    @Value(value = "${jumpUrl.appConsignmentSendContract}")
    private String appConsignmentSendContract;

    /**app承运合同*/
    @Value(value = "${jumpUrl.appAcceptanceSendContract}")
    private String appAcceptanceSendContract;


    @Value(value = "${filePathPrefix}")
    private String filePathPrefix;

    /**
     * @return PageResult
     * @desc: 分页查询
     * @param: reqVo
     * @author: sky
     * @date 2023/7/17
     */
    public PageResult queryListByPage(QueryListReqVo reqVo) {
        PageHelper.startPage(reqVo.getPage(), reqVo.getPageSize());
        QueryListReqDto queryListReqDto = new QueryListReqDto();
        BeanUtils.copyProperties(reqVo, queryListReqDto);
        List<Long> allEnt = new ArrayList<>();
        if (Objects.isNull(reqVo.getEntId())) {
            queryListReqDto.setEntId(LoginUserHolder.getEntId());
        }
        allEnt.add(queryListReqDto.getEntId());

        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(queryListReqDto.getEntId());
        if (Objects.nonNull(entCacheResDto)) {
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntTreeById(entCacheResDto.getId());
            List<EntCacheResDto> child = entCacheResDto1.getChild();
            if (CollectionUtils.isNotEmpty(child)) {
                allEnt.addAll(child.stream().map(EntCacheResDto::getId).toList());
            }
        }
        queryListReqDto.setAllEnt(allEnt);
        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryList(queryListReqDto);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            return PageHelperUtil.getPageResult(new PageInfo<>());
        }

        List<QueryListResVo> list = getQueryListResVos(queryListResDtos);
        return PageHelperUtil.getPageResult(new PageInfo<>(list), queryListResDtos, reqVo.getPageSize());
    }


    /**
     * @param queryListResDtos 入参
     * @return QueryListResVo
     * @desc: 抽取公共部分
     * @author: czh
     * @date: 2023/7/18
     */
    private List<QueryListResVo> getQueryListResVos(List<QueryListResDto> queryListResDtos) {
        Map<Long, UserCacheResDto> longUserCacheResDtoMap = new HashMap<>(8);
        List<Long> initiateByList = queryListResDtos.stream().map(QueryListResDto::getInitiateBy).toList();
        if (CollectionUtils.isNotEmpty(initiateByList)) {
            longUserCacheResDtoMap = remoteSystemService.queryUserCacheMapByIds(initiateByList);
        }

        List<QueryListResVo> list = new ArrayList<>();
        for (QueryListResDto queryListResDto : queryListResDtos) {
            QueryListResVo queryListResVo = new QueryListResVo();
            BeanUtils.copyProperties(queryListResDto, queryListResVo);


            if (Objects.nonNull(queryListResDto.getUnitType())) {
                queryListResVo.setProvideEntName(queryListResDto.getUnitType().compareTo(EntTypeEnum.SUPPLIER.getCode()) == 0 ? queryListResDto.getEntName() : queryListResDto.getTargetEntName());
                queryListResVo.setPurchaseEntName(queryListResDto.getUnitType().compareTo(EntTypeEnum.SUPPLIER.getCode()) == 0 ? queryListResDto.getTargetEntName() : queryListResDto.getEntName());
            }

            UserCacheResDto userCacheResDto = longUserCacheResDtoMap.get(queryListResDto.getInitiateBy());
            if (Objects.nonNull(userCacheResDto)) {
                queryListResVo.setInitiateName(userCacheResDto.getName());
                queryListResVo.setInitiateEntName(Objects.isNull(userCacheResDto.getEntInfo()) ? "" : userCacheResDto.getEntInfo().getFirmName());
            }
            queryListResVo.setTradingName(DictEnum.getLabel(DictTypeEnum.TRADE_TYPE.getType(), String.valueOf(queryListResDto.getTrading())));
            queryListResVo.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(queryListResDto.getStatus())).getName());
            queryListResVo.setSigningWayName(DictEnum.getLabel(DictTypeEnum.SIGNING_TYPE.getType(), queryListResDto.getSigningWay()));
            queryListResVo.setSigningWay(queryListResDto.getSigningWay());
            queryListResVo.setAmount(queryListResDto.getAmount());
            queryListResVo.setPerformedAmount(queryListResDto.getPerformedAmount());

            if(Objects.nonNull(queryListResVo.getEndTime())) {
                queryListResVo.setEndTime(DateUtils.getStartOfDay(queryListResVo.getEndTime()));
            }
            list.add(queryListResVo);
        }
        return list;
    }

    @Transactional(rollbackFor = {})
    public Long addTradeContract(ContractTradeReqVo reqVo) {
        TradeBaseInfoReqVo baseInfo = reqVo.getBaseInfo();
        List<TradeGoodsInfoReqVo> goodsInfoList = reqVo.getGoodsInfo();
        //校验
        checkParam(baseInfo, goodsInfoList);

        Long id = reqVo.getId();
        //不为空时是修改
        if (Objects.nonNull(id)) {
            update(reqVo);
            return id;
        }

        //创建合同
        KwcContractTrade kwcContractTrade = getKwcContractTrade(baseInfo, reqVo.getGoodsInfo(), reqVo.getRemark(), reqVo.getPid());
        long contactId = new IdWorker(1L).nextId();
        kwcContractTrade.setId(contactId);
        kwcContractTrade.setStatus(ContractStatusEnum.SAVE.getCode());
        String contractFile = reqVo.getContractFile();
        if (StringUtils.isNotBlank(contractFile)) {
            JSONArray jsonArray = JSONArray.parseArray(contractFile);
            for (int n = 0; n < jsonArray.size(); n++) {
                JSONObject jsonObject = jsonArray.getJSONObject(n);
                String url = jsonObject.getString("url");
                jsonObject.put("url", FileUtils.replaceAll(url));
            }
            kwcContractTrade.setSigningUrl(JSON.toJSONString(jsonArray));
        }

        if (kwcContractTradeMapper.insert(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.INSERT_FAIL);
        }

        //保存交易合同商品信息
        kwcContractTradeGoodsService.saveContractTradeGoods(contactId, goodsInfoList);

        //存单位信息
        kwcContractTradeUnitService.saveContractTradeUnit(contactId, baseInfo);
        return contactId;
    }


    private void checkParam(TradeBaseInfoReqVo baseInfo, List<TradeGoodsInfoReqVo> goodsInfo) {
        if (Objects.nonNull(baseInfo)) {
            if (StringUtils.isNotBlank(baseInfo.getContractCode()) && baseInfo.getContractCode().length() > 20) {
                throw new SystemException("合同编号超长！");
            }

            if (StringUtils.isNotBlank(baseInfo.getContractName()) && baseInfo.getContractName().length() > 20) {
                throw new SystemException("合同名称超长！");
            }
        }

        if (CollectionUtils.isNotEmpty(goodsInfo)) {
            for (TradeGoodsInfoReqVo goodsInfoReqVo : goodsInfo) {
                if (Objects.nonNull(goodsInfoReqVo.getPrice()) && !RegularUtils.matchNumberWithFix(goodsInfoReqVo.getPrice().toString(), 10, 2)) {
                    throw new SystemException("单价超长！");
                }

                if (Objects.nonNull(goodsInfoReqVo.getAmount()) && !RegularUtils.matchNumberWithFix(goodsInfoReqVo.getAmount().toString(), 10, 2)) {
                    throw new SystemException("采购数量超长！");
                }
            }
        }
    }


    /**
     * @param baseInfo 贸易基本信息 remark备注  pid父id
     * @return KwcContractTrade
     * @desc: 抽取公共
     * @author: czh
     * @date: 2023/7/20
     */
    public KwcContractTrade getKwcContractTrade(TradeBaseInfoReqVo baseInfo, List<TradeGoodsInfoReqVo> goodsInfo, String remark, Long pid) {
        Date date = new Date();
        KwcContractTrade kwcContractTrade = new KwcContractTrade();
        kwcContractTrade.setEntId(LoginUserHolder.getEntId());
        kwcContractTrade.setContractNo(baseInfo.getContractCode());
        kwcContractTrade.setName(baseInfo.getContractName());
        kwcContractTrade.setSigningWay(baseInfo.getSigningWay());
        kwcContractTrade.setTrading(baseInfo.getTrading());
        kwcContractTrade.setStartTime(baseInfo.getStartTime());
        if (Objects.nonNull(baseInfo.getEndTime())) {
            kwcContractTrade.setEndTime(DateUtils.getEndOfDay(baseInfo.getEndTime()));
        }
        kwcContractTrade.setPerformedAmount(new BigDecimal("0"));
        kwcContractTrade.setContractPid(pid);
        kwcContractTrade.setRemark(remark);
        kwcContractTrade.setCreateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setCreateTime(date);
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setUpdateTime(date);
        kwcContractTrade.setDelFlag(Global.NO);

        BigDecimal amountTotal = new BigDecimal(Global.NUMERICAL_ZERO);
        if (CollectionUtils.isNotEmpty(goodsInfo)) {
            for (TradeGoodsInfoReqVo tradeGoodsInfoReqVo : goodsInfo) {
                if (Objects.nonNull(tradeGoodsInfoReqVo.getAmount())) {
                    amountTotal = amountTotal.add(tradeGoodsInfoReqVo.getAmount());
                }
            }
        }
        kwcContractTrade.setAmount(amountTotal);
        return kwcContractTrade;
    }

    /**
     * @param reqVo 补充入参
     * @desc: 补充合同
     * @author: czh
     * @date: 2023/7/14
     */
    public void supplement(ContractTradeReqVo reqVo) {
        Long id = reqVo.getPid();
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(id);
        if (Objects.isNull(kwcContractTrade)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.CONTRACT_NOT_EXISTS);
        }

        submit(reqVo);
//        addTradeContract(reqVo);
    }


    /**
     * @param id 合同id
     * @return ContractTradeDetailResVo
     * @desc: 合同详情
     * @author: czh
     * @date 2023/7/16
     */
    public ContractTradeDetailResVo detail(Long id) {
        //基础信息
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(id);
        if (Objects.isNull(kwcContractTrade)) {
            return null;
        }

        return buildContractTradeDetailResVo(kwcContractTrade);
    }


    /**
     * @param kwcContractTrade 合同实体
     * @return ContractTradeDetailResVo
     * @desc: 构建返参
     * @author: czh
     * @date: 2023/7/20
     */
    private ContractTradeDetailResVo buildContractTradeDetailResVo(KwcContractTrade kwcContractTrade) {
        Long id = kwcContractTrade.getId();
        TradeBaseInfoResVo tradeBaseInfoResVo = new TradeBaseInfoResVo();
        tradeBaseInfoResVo.setContractCode(kwcContractTrade.getContractNo());
        tradeBaseInfoResVo.setContractName(kwcContractTrade.getName());
        tradeBaseInfoResVo.setEndTime(Objects.isNull(kwcContractTrade.getEndTime()) ? Global.EMPTY_STRING : DateUtils.format(kwcContractTrade.getEndTime()));
        tradeBaseInfoResVo.setSigningWayName(DictEnum.getLabel(DictTypeEnum.SIGNING_WAY.getType(), String.valueOf(kwcContractTrade.getSigningWay())));
        tradeBaseInfoResVo.setSigningWay(StringUtils.objectStr(kwcContractTrade.getSigningWay()));
        tradeBaseInfoResVo.setStartTime(kwcContractTrade.getStartTime());
        tradeBaseInfoResVo.setTradingName(DictEnum.getLabel(DictTypeEnum.TRADE_TYPE.getType(), String.valueOf(kwcContractTrade.getTrading())));
        tradeBaseInfoResVo.setTrading(StringUtils.objectStr(kwcContractTrade.getTrading()));
        tradeBaseInfoResVo.setAmount(kwcContractTrade.getAmount());
        tradeBaseInfoResVo.setPerformedAmount(kwcContractTrade.getPerformedAmount());

        ContractTradeDetailResVo contractTradeDetailResVo = new ContractTradeDetailResVo();
        contractTradeDetailResVo.setStatus(kwcContractTrade.getStatus());
        contractTradeDetailResVo.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(kwcContractTrade.getStatus())).getName());
        contractTradeDetailResVo.setRemark(kwcContractTrade.getRemark());


        List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitService.queryByContractId(id);
        if (CollectionUtils.isNotEmpty(kwcContractTradeUnits)) {
            for (KwcContractTradeUnit kwcContractTradeUnit : kwcContractTradeUnits) {
                if (kwcContractTradeUnit.getUnitType().compareTo(EntTypeEnum.SUPPLIER.getCode()) == 0) {
                    tradeBaseInfoResVo.setProvideEntName(kwcContractTradeUnit.getFirmName());
                    tradeBaseInfoResVo.setProvidePhone(kwcContractTradeUnit.getSignPhone());
                    tradeBaseInfoResVo.setProvideContacts(kwcContractTradeUnit.getContacts());
                    tradeBaseInfoResVo.setProvideEntId(kwcContractTradeUnit.getEntId());
                }

                if (kwcContractTradeUnit.getUnitType().compareTo(EntTypeEnum.PURCHASER.getCode()) == 0) {
                    tradeBaseInfoResVo.setPurchaseEntName(kwcContractTradeUnit.getFirmName());
                    tradeBaseInfoResVo.setPurchasePhone(kwcContractTradeUnit.getSignPhone());
                    tradeBaseInfoResVo.setPurchaseContacts(kwcContractTradeUnit.getContacts());
                    tradeBaseInfoResVo.setPurchaseEntId(kwcContractTradeUnit.getEntId());
                }
            }
        }
        contractTradeDetailResVo.setBaseInfo(tradeBaseInfoResVo);
        contractTradeDetailResVo.setId(id);

        //标的信息
        List<KwcContractTradeGoods> kwcContractTradeGoodsList = kwcContractTradeGoodsService.queryGoodsInfoByContractId(id);
        Map<Long, KwpGoods> goodsMap = new HashMap<>(8);
        if (CollectionUtils.isNotEmpty(kwcContractTradeGoodsList)) {
            List<TradeGoodsInfoResVo> tradeGoodsInfoResVoList = new ArrayList<>();
            List<Long> goodsIdList = kwcContractTradeGoodsList.stream().map(KwcContractTradeGoods::getGoodsId).toList();
            goodsMap = goodsInfoService.getGoodsByIds(goodsIdList);
            StringBuilder keys = new StringBuilder();
            for (KwcContractTradeGoods item : kwcContractTradeGoodsList) {
                keys.append(DictTypeEnum.UNIT_TYPE.getType()).append(Global.POUND).append(item.getUnit()).append(Global.COMMA);
            }
            Map<String, SysDictResDto> stringSysDictResDtoMap = remoteSystemService.queryDictMapByTypeValues(keys.toString());

            for (KwcContractTradeGoods kwcContractTradeGoods : kwcContractTradeGoodsList) {
                TradeGoodsInfoResVo tradeGoodsInfoResVo = new TradeGoodsInfoResVo();
                tradeGoodsInfoResVo.setAmount(kwcContractTradeGoods.getAmount());
                tradeGoodsInfoResVo.setPrice(kwcContractTradeGoods.getPrice());
                tradeGoodsInfoResVo.setUnit(kwcContractTradeGoods.getUnit());
                tradeGoodsInfoResVo.setGoodsId(kwcContractTradeGoods.getGoodsId());
                KwpGoods kwpGoods = goodsMap.get(kwcContractTradeGoods.getGoodsId());
                if (Objects.nonNull(kwpGoods)) {
                    tradeGoodsInfoResVo.setGoodsName(kwpGoods.getName());
                }

                SysDictResDto sysDictResDto = stringSysDictResDtoMap.get(DictTypeEnum.UNIT_TYPE.getType() + Global.POUND + kwcContractTradeGoods.getUnit());
                if (Objects.nonNull(sysDictResDto)) {
                    tradeGoodsInfoResVo.setUnitName(sysDictResDto.getLabel());
                }

                tradeGoodsInfoResVoList.add(tradeGoodsInfoResVo);
            }
            contractTradeDetailResVo.setGoodsInfo(tradeGoodsInfoResVoList);
        }

        //合同文件
        List<String> fileList = new ArrayList<>();
        String signedUrl = kwcContractTrade.getSignedUrl();
        if (StringUtils.isNotBlank(signedUrl)) {
            JSONArray jsonArray = JSONArray.parseArray(signedUrl);
            for (int n = 0; n < jsonArray.size(); n++) {
                JSONObject jsonObject = jsonArray.getJSONObject(n);
                String url = jsonObject.getString("url");
                jsonObject.put("url", FileUtils.splice(url));
            }
            fileList.add(JSON.toJSONString(jsonArray));
        }

        String signingUrl = kwcContractTrade.getSigningUrl();
        if (StringUtils.isNotBlank(signingUrl)) {
            JSONArray jsonArray = JSONArray.parseArray(signingUrl);
            for (int n = 0; n < jsonArray.size(); n++) {
                JSONObject jsonObject = jsonArray.getJSONObject(n);
                String url = jsonObject.getString("url");
                jsonObject.put("url", FileUtils.splice(url));
            }
            fileList.add(JSON.toJSONString(jsonArray));
        }
        
        contractTradeDetailResVo.setContractFile(fileList.stream().filter(StringUtils::isNotBlank).toList());

        //流程记录
        contractTradeDetailResVo.setTrackInfo(kwcContractTradeTrackService.queryContractTrackByContractId(kwcContractTrade.getId()));

        List<KwcContractTrade> supplementList = getSupplementList(id);
        if (CollectionUtils.isNotEmpty(supplementList)) {
            List<ContractTradeDetailResVo> child = new ArrayList<>();
            for (KwcContractTrade supplement : supplementList) {
                child.add(buildContractTradeDetailResVo(supplement));
            }
            contractTradeDetailResVo.setChild(child);
        }
        return contractTradeDetailResVo;
    }


    private List<KwcContractTrade> getSupplementList(Long id) {
        LambdaQueryWrapper<KwcContractTrade> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwcContractTrade::getContractPid, id);
        wrapper.eq(KwcContractTrade::getDelFlag, Global.NO);
//        wrapper.eq(KwcContractTrade::getStatus, Global.NO);
        return kwcContractTradeMapper.selectList(wrapper);
    }


    /**
     * @param reqVo id
     * @desc: 发起签约
     * @author: czh
     * @date 2023/7/16
     */
    @Transactional(rollbackFor = {})
    public Long submit(ContractTradeReqVo reqVo) {
        Long id = reqVo.getId();
        if (Objects.isNull(id)) {
            //创建合同
            id = addTradeContract(reqVo);
            changeToSubmit(id);
            sign(reqVo, id);
            return id;
        }
        update(reqVo);
        changeToSubmit(id);
        sign(reqVo, id);
        return id;
    }

    /**
     * @param reqVo 入参 id合同id
     * @desc: 签约
     * @author: czh
     * @date: 2023/8/18
     */
    private void sign(ContractTradeReqVo reqVo, Long id) {
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(id);
        if (DictEnum.SIGNING_WAY_1.getValue().equals(String.valueOf(reqVo.getBaseInfo().getSigningWay()))) {
            commonBusinessService.postToEsign(reqVo.getBaseInfo().getProvidePhone(),
                    reqVo.getBaseInfo().getPurchasePhone(),
                    reqVo.getBaseInfo().getProvideEntId(),
                    reqVo.getBaseInfo().getPurchaseEntId(),
                    reqVo.getContractFile(),
                    id,
                    reqVo.getBaseInfo().getContractName());
            sendTradeMessage(kwcContractTrade);
        }

        //线下签约直接通过
        if (DictEnum.SIGNING_WAY_2.getValue().equals(String.valueOf(reqVo.getBaseInfo().getSigningWay()))) {
            ESignCallBackReqVo eSignCallBackReqVo = new ESignCallBackReqVo();
            eSignCallBackReqVo.setContractId(id);
            eSignCallBackReqVo.setStatus(ContractStatusEnum.SIGNED.getCode());
            //发送消息
            sendTradeMessage(kwcContractTrade);
            //审批通过
            commonBusinessService.approval(eSignCallBackReqVo);
        }
    }


    private void sendTradeMessage(KwcContractTrade kwcContractTrade) {
        try {
            List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitService.queryByContractId(kwcContractTrade.getId());
            Map<Integer, KwcContractTradeUnit> collect = kwcContractTradeUnits.stream().collect(Collectors.toMap(KwcContractTradeUnit::getUnitType, Function.identity()));
            KwcContractTradeUnit kwcContractTradeUnit = collect.get(CooperateTypeEnum.PURCHASER.getCode());
            EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(kwcContractTradeUnit.getEntId());
            Map<String, Object> map = new HashMap<>();
            map.put("entName", entCacheResDto.getFirmName());
            map.put("contract_no", kwcContractTrade.getContractNo());
            map.put("name", kwcContractTrade.getName());
            MessageEnum messageEnum;
            if (Objects.nonNull(kwcContractTrade.getContractPid())) {
                messageEnum = MessageEnum.SAELCONTRACT_SUBMIT_DATA;
            } else {
                messageEnum = MessageEnum.SAELCONTRACT_SEND_CONTRACT;
            }
            commonBusinessService.sendSystemMessage(Collections.singletonList(new UserInfo().setUserId(kwcContractTrade.getCreateBy()).setEntId(kwcContractTrade.getEntId())),
                    messageEnum,
                    map,
                    saleSendContract,
                    appSaleSendContract);


            if (Objects.nonNull(kwcContractTrade.getContractPid())) {
                messageEnum = MessageEnum.BUYCONTRACT_SUPPLYPROCESS_SEND;
            } else {
                messageEnum = MessageEnum.BUYCONTRACT_PROCESS_SEND;
            }

            EntCacheResDto entCacheResDto2 = remoteSystemService.queryEntTreeById(kwcContractTradeUnit.getEntId());
            KwcContractTradeUnit kwcContractTradeUnit2 = collect.get(CooperateTypeEnum.SUPPLIER.getCode());
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntCacheById(kwcContractTradeUnit2.getEntId());
            map.put("entName", entCacheResDto1.getFirmName());
            commonBusinessService.sendSystemMessage(Collections.singletonList(new UserInfo().setUserId(entCacheResDto2.getContactsId()).setEntId(entCacheResDto2.getId())),
                    messageEnum,
                    map,
                    purchaseSendContract,
                    appPurchaseSendContract);
        } catch (Exception e) {
           log.error("合同签约流程已发起消息出错：", e);
        }
    }



    /**
     * @param id 合同id
     * @desc: 更新合同为发起
     * @author: czh
     * @date: 2023/7/20
     */
    private void changeToSubmit(Long id) {
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(id);
        int code = ContractStatusEnum.SUBMIT.getCode();
        kwcContractTrade.setStatus(code);
        if (kwcContractTradeMapper.updateById(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }
        kwcContractTradeTrackService.saveContractTradeTrack(id, code);
    }

    /**
     * @desc: 修改草稿
     * @param: reqVo 入参
     * @author: czh
     * @date 2023/7/16
     */
    @Transactional(rollbackFor = {})
    public void update(ContractTradeReqVo reqVo) {
        Long contractId = reqVo.getId();
        Date date = new Date();
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(contractId);
        if (Objects.isNull(kwcContractTrade)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.CONTRACT_NOT_EXISTS);
        }
        KwcContractTrade param = getKwcContractTrade(reqVo.getBaseInfo(), reqVo.getGoodsInfo(), reqVo.getRemark(), reqVo.getPid());

        TradeBaseInfoReqVo baseInfo = reqVo.getBaseInfo();
        kwcContractTrade.setEntId(LoginUserHolder.getEntId());
        kwcContractTrade.setContractNo(baseInfo.getContractCode());
        kwcContractTrade.setName(baseInfo.getContractName());
        kwcContractTrade.setSigningWay(baseInfo.getSigningWay());
        kwcContractTrade.setTrading(baseInfo.getTrading());
        kwcContractTrade.setStartTime(baseInfo.getStartTime());
        kwcContractTrade.setEndTime(baseInfo.getEndTime());
        if (Objects.nonNull(baseInfo.getEndTime())) {
            kwcContractTrade.setEndTime(DateUtils.getEndOfDay(baseInfo.getEndTime()));
        }
        kwcContractTrade.setPerformedAmount(new BigDecimal("0"));
        kwcContractTrade.setContractPid(reqVo.getPid());
        kwcContractTrade.setRemark(reqVo.getRemark());

        List<TradeGoodsInfoReqVo> goodsInfo = reqVo.getGoodsInfo();
        BigDecimal amountTotal = new BigDecimal(Global.NUMERICAL_ZERO);
        if (CollectionUtils.isNotEmpty(goodsInfo)) {
            for (TradeGoodsInfoReqVo tradeGoodsInfoReqVo : goodsInfo) {
                if (Objects.nonNull(tradeGoodsInfoReqVo.getAmount())) {
                    amountTotal = amountTotal.add(tradeGoodsInfoReqVo.getAmount());
                }
            }
        }
        kwcContractTrade.setAmount(amountTotal);
        kwcContractTrade.setSigningUrl(reqVo.getContractFile());
        kwcContractTrade.setStatus(ContractStatusEnum.SAVE.getCode());
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setUpdateTime(date);
        if (kwcContractTradeMapper.updateById(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }


        //保存交易合同商品信息-先把以前的删除
        List<KwcContractTradeGoods> kwcContractTradeGoodsList = kwcContractTradeGoodsService.queryGoodsInfoByContractId(contractId);
        if (CollectionUtils.isNotEmpty(kwcContractTradeGoodsList)) {
            kwcContractTradeGoodsList.forEach(item -> {
                item.setDelFlag(Global.YES);
                item.setUpdateBy(LoginUserHolder.getUserId());
                item.setUpdateTime(date);
            });

            if (kwcContractTradeGoodsService.updateBatch(kwcContractTradeGoodsList) != kwcContractTradeGoodsList.size()) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
            }
        }
        kwcContractTradeGoodsService.saveContractTradeGoods(kwcContractTrade.getId(), reqVo.getGoodsInfo());

        //保存单位信息-先把以前的删除
        List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitService.queryByContractId(contractId);
        if (CollectionUtils.isNotEmpty(kwcContractTradeUnits)) {
            kwcContractTradeUnits.forEach(item -> {
                item.setDelFlag(Global.YES);
                item.setUpdateBy(LoginUserHolder.getUserId());
                item.setUpdateTime(date);
            });

            if (kwcContractTradeUnitService.updateBatch(kwcContractTradeUnits) != kwcContractTradeUnits.size()) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
            }
        }
        kwcContractTradeUnitService.saveContractTradeUnit(contractId, reqVo.getBaseInfo());
    }


    /**
     * @desc: 手动完结
     * @param: reqVo ids
     * @author: czh
     * @date 2023/7/16
     */
    @Transactional(rollbackFor = {})
    public void complete(CompleteReqVo reqVo) {
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectById(reqVo.getId());
        if (!kwcContractTrade.getStatus().equals(ContractStatusEnum.SIGNED.getCode())) {
            throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_028);
        }
        kwcContractTrade.setStatus(ContractStatusEnum.COMPLETE.getCode());
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        kwcContractTrade.setUpdateTime(new Date());
        kwcContractTrade.setPerformedAmount(reqVo.getPerformedAmount());
        kwcContractTrade.setRemark(reqVo.getRemark());
        if (kwcContractTradeMapper.updateById(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }
        kwcContractTradeTrackService.saveContractTradeTrack(kwcContractTrade.getId(), ContractTrackEnum.OVER.getCode());

        //完结相关订单
        ContractSignCompletedParam contractSignCompletedParam = new ContractSignCompletedParam();
        contractSignCompletedParam.setContractId(kwcContractTrade.getContractPid());
        contractSignCompletedParam.setUpdateBy(LoginUserHolder.getUserId());
        contractSignCompletedParam.setUpdateByName(LoginUserHolder.getUserName());
        tradeOrderInfoService.contractSignCompleted(contractSignCompletedParam);

        //发送消息
        try {
            List<KwcContractTradeUnit> kwcContractTradeUnits = kwcContractTradeUnitService.queryByContractId(kwcContractTrade.getId());
            Map<Integer, KwcContractTradeUnit> collect = kwcContractTradeUnits.stream().collect(Collectors.toMap(KwcContractTradeUnit::getUnitType, Function.identity()));
            KwcContractTradeUnit kwcContractTradeUnit = collect.get(CooperateTypeEnum.PURCHASER.getCode());
            Long entId = kwcContractTradeUnit.getEntId();
            EntCacheResDto entCacheResDto = remoteSystemService.queryEntCacheById(entId);
            Map<String, Object> map = new HashMap<>();
            map.put("entName", entCacheResDto.getFirmName());
            map.put("contract_no", kwcContractTrade.getContractNo());
            map.put("name", kwcContractTrade.getName());

            commonBusinessService.sendSystemMessage(Collections.singletonList(new UserInfo().setUserId(kwcContractTrade.getCreateBy()).setEntId(kwcContractTrade.getEntId())),
                    MessageEnum.SAELCONTRACT_COMPLETE_CONTRACT,
                    map,
                    saleSendContract,
                    appSaleSendContract);


            KwcContractTradeUnit kwcContractTradeUnit2 = collect.get(CooperateTypeEnum.SUPPLIER.getCode());
            Long entId1 = kwcContractTradeUnit2.getEntId();
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntCacheById(entId1);
            EntCacheResDto entCacheResDto2 = remoteSystemService.queryEntTreeById(entId);
            map.put("entName", entCacheResDto1.getFirmName());
            commonBusinessService.sendSystemMessage(Collections.singletonList(new UserInfo().setUserId(entCacheResDto2.getContactsId()).setEntId(entCacheResDto2.getId())),
                    MessageEnum.BUYCONTRACT_COMPLETE_CONTRACT,
                    map,
                    purchaseSendContract,
                    appPurchaseSendContract);
        } catch (Exception e) {
            log.error("完结合同消息出错:", e);
        }
    }


    /**
     * @desc: 手动完结
     * @param: reqVo ids
     * @author: czh
     * @date 2023/7/16
     */
    @Transactional(rollbackFor = {})
    public void delete(String ids) {
        List<Long> contractIdList = Arrays.stream(ids.split(Global.COMMA)).map(Long::parseLong).toList();
        List<KwcContractTrade> kwcContractTradeList = kwcContractTradeMapper.selectBatchIds(contractIdList);
        Date date = new Date();
        kwcContractTradeList.forEach(item -> {
            if (!item.getStatus().equals(ContractStatusEnum.SAVE.getCode())) {
                throw new SystemException(HttpStatus.CODE_10301, HttpStatus.MSG_022);
            }
            item.setDelFlag(Global.YES);
            item.setUpdateBy(LoginUserHolder.getUserId());
            item.setUpdateTime(date);
            if (kwcContractTradeMapper.updateById(item) <= 0) {
                throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
            }
        });
    }

    /**
     * @param reqVo 查询入参
     * @desc: 导出
     * @author: czh
     * @date 2023/7/17
     */
    public void export(QueryListReqVo reqVo, HttpServletResponse response) {
        QueryListReqDto queryListReqDto = new QueryListReqDto();
        BeanUtils.copyProperties(reqVo, queryListReqDto);
        queryListReqDto.setIdList(StringUtils.splitStrToList(reqVo.getIds(), Global.COMMA, Long.class));
        List<Long> allEnt = new ArrayList<>();
        if (Objects.isNull(reqVo.getEntId())) {
            queryListReqDto.setEntId(LoginUserHolder.getEntId());
        }
        allEnt.add(queryListReqDto.getEntId());

        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(queryListReqDto.getEntId());
        if (Objects.nonNull(entCacheResDto)) {
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntTreeById(entCacheResDto.getId());
            List<EntCacheResDto> child = entCacheResDto1.getChild();
            if (CollectionUtils.isNotEmpty(child)) {
                allEnt.addAll(child.stream().map(EntCacheResDto::getId).toList());
            }
        }
        queryListReqDto.setAllEnt(allEnt);
        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryList(queryListReqDto);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            throw new SystemException(HttpStatus.SUCCESS_CODE, "暂无数据，请确认！");
        }

        List<QueryListResVo> list = getQueryListResVos(queryListResDtos);
        List<TradeListExport> dataList = BeanUtils.copyToList(list, TradeListExport.class);
        ExcelUtil.downData(response, TradeListExport.class, dataList);
    }

    /**
     * @return HttpResult
     * @desc: 查询当前企业的销售合同
     * @author: czh
     * @date: 2023/7/18
     */
    public List<QueryListResVo> queryCurrentEntSaleContractList() {
        Long entId = LoginUserHolder.getEntId();
        QueryListReqDto queryListReqDto = new QueryListReqDto();
        queryListReqDto.setEntId(entId);
        queryListReqDto.setStatus(ContractStatusEnum.SIGNED.getCode());
        queryListReqDto.setEntType(EntTypeEnum.SUPPLIER.getCode());
        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryList(queryListReqDto);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            return Collections.emptyList();
        }
        return getQueryListResVos(queryListResDtos);
    }


    /**
     * @return FindListGroupResVo
     * @desc: 分组查询
     * @author: czh
     * @date: 2023/7/18
     */
    public List<FindListGroupResVo> findListGroup(QueryListReqVo reqVo) {
        ContractStatusEnum[] values = ContractStatusEnum.values();
        List<FindListGroupResVo> list = new ArrayList<>();
        FindListGroupResVo total = new FindListGroupResVo();
        total.setCount(0);
        list.add(total);
        for (ContractStatusEnum contractStatusEnum : values) {
            FindListGroupResVo findListGroupResVo = new FindListGroupResVo();
            findListGroupResVo.setStatus(contractStatusEnum.getCode());
            findListGroupResVo.setStatusName(contractStatusEnum.getName());
            findListGroupResVo.setCount(0);
            list.add(findListGroupResVo);
        }

        QueryListReqDto queryListReqDto = new QueryListReqDto();
        BeanUtils.copyProperties(reqVo, queryListReqDto);
        List<Long> allEnt = new ArrayList<>();
        if (Objects.isNull(reqVo.getEntId())) {
            queryListReqDto.setEntId(LoginUserHolder.getEntId());
        }
        allEnt.add(queryListReqDto.getEntId());

        EntCacheResDto entCacheResDto = remoteSystemService.queryEntTreeById(queryListReqDto.getEntId());
        if (Objects.nonNull(entCacheResDto)) {
            EntCacheResDto entCacheResDto1 = remoteSystemService.queryEntTreeById(entCacheResDto.getId());
            List<EntCacheResDto> child = entCacheResDto1.getChild();
            if (CollectionUtils.isNotEmpty(child)) {
                allEnt.addAll(child.stream().map(EntCacheResDto::getId).toList());
            }
        }
        queryListReqDto.setAllEnt(allEnt);
        List<QueryListResDto> queryListResDtoList = kwcContractTradeMapper.queryList(queryListReqDto);
        if (CollectionUtils.isNotEmpty(queryListResDtoList)) {
            Map<Integer, List<QueryListResDto>> collect = queryListResDtoList.stream().collect(Collectors.groupingBy(QueryListResDto::getStatus));
            for (FindListGroupResVo findListGroupResVo : list) {
                List<QueryListResDto> queryListResDtos = collect.get(findListGroupResVo.getStatus());
                findListGroupResVo.setCount(CollectionUtils.isEmpty(queryListResDtos) ? Global.NUMERICAL_ZERO : queryListResDtos.size());
            }
            //给汇总项求和
            list.get(0).setCount(queryListResDtoList.size());
        }
        return list;
    }


    @Transactional(rollbackFor = {})
    public void approval(Long id, Integer status, String remark) {
        LambdaQueryWrapper<KwcContractTrade> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(KwcContractTrade::getId, id).
                eq(KwcContractTrade::getDelFlag, Global.NO).
                eq(KwcContractTrade::getStatus, ContractStatusEnum.SUBMIT.getCode());
        KwcContractTrade kwcContractTrade = kwcContractTradeMapper.selectOne(wrapper);
        if (Objects.isNull(kwcContractTrade)) {
            throw new SystemException(HttpStatus.QUERY_FAIL_CODE, HttpStatus.CONTRACT_NOT_EXISTS);
        }

        Date date = new Date();
        kwcContractTrade.setStatus(status);
        kwcContractTrade.setRemark(remark);
        kwcContractTrade.setUpdateTime(date);
        kwcContractTrade.setUpdateBy(LoginUserHolder.getUserId());
        if (kwcContractTradeMapper.updateById(kwcContractTrade) <= 0) {
            throw new SystemException(HttpStatus.CRUD_FAIL_CODE, HttpStatus.UPDATE_FAIL);
        }
    }

    /**
     * @param reqVo 分页查询
     * @return PageResult
     * @desc: 运营端查贸易合同
     * @author: czh
     * @date: 2023/9/13
     */
    public PageResult queryTradeByPage(QueryListReqVo reqVo) {
        PageHelper.startPage(reqVo.getPage(), reqVo.getPageSize());
        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryTradeList(reqVo);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            return PageHelperUtil.getPageResult(new PageInfo<>());
        }

        List<QueryListResVo> list = getTradeListResVo(queryListResDtos);
        return PageHelperUtil.getPageResult(new PageInfo<>(list), queryListResDtos, reqVo.getPageSize());
    }

    private List<QueryListResVo> getTradeListResVo(List<QueryListResDto> queryListResDtos) {
        Map<Long, UserCacheResDto> longUserCacheResDtoMap = new HashMap<>(8);
        List<Long> initiateByList = queryListResDtos.stream().map(QueryListResDto::getInitiateBy).toList();
        if (CollectionUtils.isNotEmpty(initiateByList)) {
            longUserCacheResDtoMap = remoteSystemService.queryUserCacheMapByIds(initiateByList);
        }

        List<QueryListResVo> list = new ArrayList<>();
        for (QueryListResDto queryListResDto : queryListResDtos) {
            QueryListResVo queryListResVo = new QueryListResVo();
            BeanUtils.copyProperties(queryListResDto, queryListResVo);

            UserCacheResDto userCacheResDto = longUserCacheResDtoMap.get(queryListResDto.getInitiateBy());
            if (Objects.nonNull(userCacheResDto)) {
                queryListResVo.setInitiateName(userCacheResDto.getName());
                queryListResVo.setInitiateEntName(Objects.isNull(userCacheResDto.getEntInfo()) ? "" : userCacheResDto.getEntInfo().getFirmName());
            }
            queryListResVo.setTradingName(DictEnum.getLabel(DictTypeEnum.TRADE_TYPE.getType(), String.valueOf(queryListResDto.getTrading())));
            queryListResVo.setStatusName(Objects.requireNonNull(ContractStatusEnum.getName(queryListResDto.getStatus())).getName());
            queryListResVo.setSigningWayName(DictEnum.getLabel(DictTypeEnum.SIGNING_TYPE.getType(), queryListResDto.getSigningWay()));
            queryListResVo.setSigningWay(queryListResDto.getSigningWay());
            queryListResVo.setAmount(queryListResDto.getAmount());
            queryListResVo.setPerformedAmount(queryListResDto.getPerformedAmount());
            list.add(queryListResVo);
        }
        return list;
    }

    /**
     * @return HttpResult
     * @desc: 分组查询
     * @author: czh
     * @date: 2023/7/18
     */
    public List<FindListGroupResVo> findTradeListGroup(QueryListReqVo reqVo) {
        ContractStatusEnum[] values = ContractStatusEnum.values();
        List<FindListGroupResVo> list = new ArrayList<>();
        FindListGroupResVo total = new FindListGroupResVo();
        total.setCount(0);
        list.add(total);
        for (ContractStatusEnum contractStatusEnum : values) {
            FindListGroupResVo findListGroupResVo = new FindListGroupResVo();
            findListGroupResVo.setStatus(contractStatusEnum.getCode());
            findListGroupResVo.setStatusName(contractStatusEnum.getName());
            findListGroupResVo.setCount(0);
            list.add(findListGroupResVo);
        }

        List<QueryListResDto> queryListResDtoList = kwcContractTradeMapper.queryTradeList(reqVo);
        if (CollectionUtils.isNotEmpty(queryListResDtoList)) {
            Map<Integer, List<QueryListResDto>> collect = queryListResDtoList.stream().collect(Collectors.groupingBy(QueryListResDto::getStatus));
            for (FindListGroupResVo findListGroupResVo : list) {
                List<QueryListResDto> queryListResDtos = collect.get(findListGroupResVo.getStatus());
                findListGroupResVo.setCount(CollectionUtils.isEmpty(queryListResDtos) ? Global.NUMERICAL_ZERO : queryListResDtos.size());
            }
            //给汇总项求和
            list.get(0).setCount(queryListResDtoList.size());
        }
        return list;
    }


    /**
     * @param reqVo 查询参数
     * @desc: 运营端查贸易合同导出
     * @author: czh
     * @date: 2023/9/13
     */
    public void exportTradeList(QueryListReqVo reqVo, HttpServletResponse response) {
        reqVo.setIdList(StringUtils.splitStrToList(reqVo.getIds(), Global.COMMA, Long.class));
        List<QueryListResDto> queryListResDtos = kwcContractTradeMapper.queryTradeList(reqVo);
        if (CollectionUtils.isEmpty(queryListResDtos)) {
            throw new SystemException(HttpStatus.SUCCESS_CODE, "暂无数据，请确认！");
        }
        List<QueryListResVo> list = getTradeListResVo(queryListResDtos);
        List<TradeListExport> dataList = BeanUtils.copyToList(list, TradeListExport.class);
        ExcelUtil.downData(response, TradeListExport.class, dataList);
    }

}