package com.jwipc.sys.logic.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Pair;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlLike;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlUtils;
import com.jwipc.api.constant.RestCode;
import com.jwipc.api.constant.SignFlowStatus;
import com.jwipc.api.dto.*;
import com.jwipc.api.esign.HTTPHelper;
import com.jwipc.api.esign.SignUtils;
import com.jwipc.constant.FlagConst;
import com.jwipc.constant.SignProcessType;
import com.jwipc.contract.base.DigitalSealConfigClientDTO;
import com.jwipc.contract.client.ContractSignClient;
import com.jwipc.exception.DaoException;
import com.jwipc.log.constant.ThirdSysType;
import com.jwipc.log.factory.ApiLogTaskFactory;
import com.jwipc.log.logic.LogManager;
import com.jwipc.order.clent.dto.PurchaseOrderDTO;
import com.jwipc.order.client.PurchaseOrderClient;
import com.jwipc.security.LoginUtil;
import com.jwipc.supplier.entity.SupplierAvl;
import com.jwipc.supplier.entity.SupplierContacts;
import com.jwipc.sys.convert.DigitalSealBusinessDetailConvert;
import com.jwipc.sys.convert.FileConvert;
import com.jwipc.sys.dto.*;
import com.jwipc.sys.entity.DigitalSealBusinessConfig;
import com.jwipc.sys.entity.DigitalSealBusinessDetail;
import com.jwipc.sys.entity.DigitalSealConfig;
import com.jwipc.sys.entity.User;
import com.jwipc.sys.logic.DictLogic;
import com.jwipc.sys.logic.ESignLogic;
import com.jwipc.sys.logic.FileLogic;
import com.jwipc.sys.service.IDigitalSealBusinessConfigService;
import com.jwipc.sys.service.IDigitalSealBusinessDetailService;
import com.jwipc.sys.service.IDigitalSealConfigService;
import com.jwipc.sys.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author shenyang.ou
 * @date 2024/5/9 14:52
 * @desc
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class ESignLogicImpl implements ESignLogic {
    private final FileLogic fileLogic;
    private final ContractSignClient contractSignClient;
    private final PurchaseOrderClient purchaseOrderClient;
    private final IDigitalSealConfigService digitalSealConfigService;
    private final IDigitalSealBusinessConfigService digitalSealBusinessConfigService;
    private final DigitalSealBusinessDetailConvert digitalSealBusinessDetailConvert;
    private final IDigitalSealBusinessDetailService digitalSealBusinessDetailService;
    private final FileConvert fileConvert;
    private final IUserService userService;
    @Value("${sys.esign.projectid}")
    private String projectid;

    private final DictLogic dictLogic;

    @Value("${sys.esign.serverip}")
    private String serverip;

    @Value("${sys.esign.projectsecret}")
    private String projectsecret;

    @Value("${sys.esign.businessTypeCode}")
    private String businessTypeCode;

    @Value("${sys.esign.callbackUrl}")
    private String callbackUrl;


    /**
     * 上传签章文件
     *
     * @param files 文件
     */
    @Override
    public List<ESignFileResposeDTO> saveSignFile(MultipartFile[] files, String fileIds) {
        List<ESignFileResposeDTO> eSignFileResposeDTOS = new ArrayList<>();
        List<String> fileIdList = Arrays.asList(StringUtils.split(fileIds, ","));
        int index = 0;
        for (MultipartFile file : files) {
            FileResposeDTO fileResposeDTO = fileLogic.getForDownload(Long.valueOf(fileIdList.get(index)));
            ESignFileResposeDTO eSignFileResposeDTO = fileConvert.toESignDto(fileResposeDTO);
            String key = this.sendFileClient(eSignFileResposeDTO, file);
            eSignFileResposeDTO.setFileKey(key);
            eSignFileResposeDTOS.add(eSignFileResposeDTO);
            index++;
        }
        return eSignFileResposeDTOS;
    }

    public String sendFileClient(ESignFileResposeDTO fileResposeDTO, MultipartFile file) {
        String getInnerOrganizationsDetailApi = "/file/v1/upload";
        String uploadApiUrl = serverip + getInnerOrganizationsDetailApi;
        JSONObject reqBodyObj = new JSONObject();
        reqBodyObj.put("file", fileResposeDTO.getFileName());
        reqBodyObj.put("hash", SignUtils.sign256("", fileResposeDTO.getHash()));
        // 请求Body体数据
        String reqBodyData = reqBodyObj.toString();
        log.info("上传盖章附件接口参数：{}", reqBodyData);
        // 构建参与请求签名计算的明文
        // 计算请求签名值
        String reqSignature = SignUtils.sign256(reqBodyData, projectsecret);

        LinkedHashMap<String, String> header = new LinkedHashMap<>();
        // 构建待签名字符串
        String accept = "*/*";
        header.put("X-timevale-project-id", projectid);
        header.put("X-timevale-signature", reqSignature);
        header.put("Accept", accept);
        String fileFieldName = "file";

        // 发送POST请求
        String result = null;
        try {
            result = HTTPHelper.uploadFile1(uploadApiUrl, fileFieldName, file, reqBodyObj, header, "UTF-8");
            log.info("上传盖章附件接口返回结果：{}", reqBodyData);
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //调用方日志
            LogManager.me().executeLog(ApiLogTaskFactory.saveCallLog("uploadFile", "上传盖章文件接口",
                    ThirdSysType.SIGN.getType(),
                    reqBodyData,
                    result,
                    "",
                    LocalDateTime.now()
            ));
        }
        System.out.println(JSON.toJSONString("result----" + result));
        ApiResult json = JSON.parseObject(result, ApiResult.class);
        if (json.getCode().equals(RestCode.MES_SUCCESS.getCode())) {
            JSONObject dataJson = (JSONObject) json.getData();
            return dataJson.getString("fileKey");
        } else {
            throw new DaoException(json.getMessage());
        }
    }

    @Override
    public void sendSign(DigitalSealBusinessDTO digitalSealBusinessDTO) {
        Map<String, List<DictDTO>> result1 = dictLogic.getDicByTypes("intercompany_supplier");
        //公司间交易
        Map<String, String> supplierConversionCode =  result1.values().stream().flatMap(List::stream).collect(Collectors.toMap(
                DictDTO::getCode,   // 值提取器
                DictDTO::getName,   // 键提取器
                (existing, replacement) -> replacement
        ));

        //获取公司对应的 E签宝信息
//        DigitalSealConfigClientDTO sealConfigDTOS = contractSignClient.selectESignDetailClient(
//                digitalSealBusinessDTO.getFirstParty(), digitalSealBusinessDTO.getSignatureType());
        //处理电子签署单签和双签时，签署状态和签署文件挂在相同汇总单号上去 2024-08-14
        DigitalSealConfig sealConfigDTOS = digitalSealConfigService.getById(
                digitalSealBusinessDTO.getFirstPartyUserName());
        if (sealConfigDTOS == null) {
            throw new DaoException("未查询到公司对应的印章信息!");
        }
        List<SignFileDTO> signFileDTOS = digitalSealBusinessDTO.getFileKeyList();
        List<DigitalSealBusinessDetail> digitalSealBusinessDetails = new ArrayList<>();
        //需要区分采购订单还是对账单电子签
        List<PurchaseOrderDTO> orderListById = null;
        List<Long> idList = null;
        if("purchase_order".equals(digitalSealBusinessDTO.getBusinessTypeCode())){
           orderListById = purchaseOrderClient.getOrderListById(digitalSealBusinessDTO.getBusinessId());
            if (CollectionUtils.isNotEmpty(orderListById)) {
                idList = orderListById.stream().map(PurchaseOrderDTO::getId).collect(Collectors.toList());
                idList.removeIf(value -> value.equals(digitalSealBusinessDTO.getBusinessId()));
            }
        }

        for (SignFileDTO signFileDTO : signFileDTOS) {
            // 构建请求Body体
            SubjectDTO subjectDTO = new SubjectDTO();
            subjectDTO.setBusinessNo(digitalSealBusinessDTO.getBusinessTypeCode());
            subjectDTO.setSubject(digitalSealBusinessDTO.getTitle());
            subjectDTO.setBusinessTypeCode(businessTypeCode);
            subjectDTO.setReadComplete(1);
            subjectDTO.setRemark("");
            subjectDTO.setSignNotifyUrl(callbackUrl);
//        subjectDTO.setRedirectUrl("www.baidu.com");

            SubjectDTO.InitiatorInfo initiatorInfo = new SubjectDTO.InitiatorInfo();
            initiatorInfo.setUserCode(sealConfigDTOS.getSignerAccount()); // 发起人 编码
            initiatorInfo.setOrganizationCode(sealConfigDTOS.getSignerOrgCode()); // 发起人 组织编码
            subjectDTO.setInitiatorInfo(initiatorInfo);

            //流程文档信息
            List<SubjectDTO.SignFiles> signFiles = new ArrayList<>();
            SubjectDTO.SignFiles signFile = new SubjectDTO.SignFiles();
            signFile.setFileKey(signFileDTO.getFileKey());
            signFiles.add(signFile);
            subjectDTO.setSignFiles(signFiles);


            SubjectDTO.ManualConfig manualConfig = new SubjectDTO.ManualConfig();
            manualConfig.setStartMode(0);
            manualConfig.setFinishMode(0);
            subjectDTO.setManualConfig(manualConfig);

            //签章顺序 1 对方先签  2我方先签  3单方签
            String signOrder = digitalSealBusinessDTO.getSignOrder();
            //签章类型  合同章 公章
//        String sealType = contract.getContractSealType();

            Boolean f = true;
            Integer orderOne = 1;
            Integer orderTow = 2;
            if (signOrder.equals("3")) {
                f = false;
            }

            List<SubjectDTO.SignerInfos> signerInfos = new ArrayList<>();

            //设置甲方信息
            SubjectDTO.SignerInfos signerInfoJf = new SubjectDTO.SignerInfos();
            signerInfoJf.setUserType(1);
            signerInfoJf.setUserCode(sealConfigDTOS.getSignerAccount());
            signerInfoJf.setOrganizationCode(sealConfigDTOS.getSignerOrgCode());
            signerInfoJf.setAutoSign(digitalSealBusinessDTO.getFirstPartyAutoSign());

            //指定印章类型
//        signerInfoJf.setSealTypeCode("PERSONNEL");

            if (f) {
                //设置 签章顺序1乙方先签章
                if (signOrder.equals("1")) {
                    signerInfoJf.setSignMode(0);
                    signerInfoJf.setSignNode(orderTow);
                    signerInfoJf.setSignOrder(orderTow);
                } else if (signOrder.equals("2")) {
                    signerInfoJf.setSignMode(0);
                    signerInfoJf.setSignNode(orderOne);
                    signerInfoJf.setSignOrder(orderOne);
                }
            } else {
                //设置 签章顺序 单签甲方 类似2（我方先签）
                signerInfoJf.setSignMode(0);
                signerInfoJf.setSignNode(orderOne);
                signerInfoJf.setSignOrder(orderOne);
            }

            //签署任务信
            List<SubjectDTO.SealInfos> sealInfosJf = new ArrayList<>();
            SubjectDTO.SealInfos sealInfoJf = new SubjectDTO.SealInfos();
            sealInfoJf.setFileKey(signFileDTO.getFileKey());
            List<SubjectDTO.SignConfigs> signConfigsJf = new ArrayList<>();
            //取出文件ID，通过文件ID读取PDF源文件，得出文件页数，如果单页，有选骑缝章的，报错， 如果是多页的，没有选骑缝章，报错。 邓京术 2025-06-11
            Integer pageNumber = digitalSealBusinessDTO.getNumberOfPages();
            if (pageNumber == null || pageNumber == 0) {
                pageNumber = purchaseOrderClient.getEsignTotalPage(signFileDTO.getFileId());
            }
            //甲方签署类型：KEYWORD-SIGN 关键字
            if (digitalSealBusinessDTO.getFirstPartySignType().contains("KEYWORD-SIGN")) {
                SubjectDTO.SignConfigs signConfigJf = new SubjectDTO.SignConfigs();
                //设置印章
                signConfigJf.setSealId(sealConfigDTOS.getSealCode());
                //指定签署印章类型：PERSON-SEAL-个人印章、COMMON-SEAL-企业授权印章、LEGAL-PERSON-SEAL-法人章
                signConfigJf.setSignatureType("COMMON-SEAL");
                //设置关键字
                SubjectDTO.KeywordInfo keywordInfoJf = new SubjectDTO.KeywordInfo();
                keywordInfoJf.setKeywordIndex(-1);
                keywordInfoJf.setOffsetPosX(Double.valueOf(digitalSealBusinessDTO.getFirstPartyKeywordPosX()));
                keywordInfoJf.setOffsetPosY(Double.valueOf(digitalSealBusinessDTO.getFirstPartyKeywordPosY()));
                keywordInfoJf.setKeyword(digitalSealBusinessDTO.getFirstPartyKeyword());
                signConfigJf.setKeywordInfo(keywordInfoJf);

                signConfigJf.setSignFieldType(0);
                signConfigJf.setAllowMove(0);
                signConfigJf.setSignType("KEYWORD-SIGN");
                signConfigsJf.add(signConfigJf);
            }
            //如果是单方签 3单方签
            if (!f) {
                if (signOrder.equals("1")) {//非f,应该不会走到这个判断。
                    //如果是1，乙方先签章，如果乙方信息没有选择骑缝且总页数大于1报错。
                    if (!digitalSealBusinessDTO.getFirstPartySignType().contains("EDGE-SIGN") && pageNumber > 1) {
                        throw new DaoException("总页数大于1页必须选择骑缝!");
                    }
                } else {
                    //3单方签如果总页数大于1，甲方信息没选择骑缝报错
                    if (!digitalSealBusinessDTO.getFirstPartySignType().contains("EDGE-SIGN") && pageNumber > 1) {
                        throw new DaoException("总页数大于1页必须选择骑缝!");
                    }
                    //3单方签如果总页数小于等于1，甲方信息选择了骑缝报错
                    if (digitalSealBusinessDTO.getFirstPartySignType().contains("EDGE-SIGN") && pageNumber <= 1) {
                        throw new DaoException("总页数大于1才能选择骑缝!");
                    }
                    //判断乙方信息是否有填，不会走到这里来。
                    if (!digitalSealBusinessDTO.getSecondPartySignType().contains("EDGE-SIGN") && pageNumber > 1) {
                        throw new DaoException("总页数大于1页必须选择骑缝!");
                    }
                }
            //签章顺序 1 对方（乙方）先签  2我方（甲方）先签
            } else {
                //如果总页数大于1页，甲方和乙方信息都必须选择骑缝。邓京术 2025-06-30
                if (pageNumber > 1 && (!digitalSealBusinessDTO.getFirstPartySignType().contains("EDGE-SIGN") || !digitalSealBusinessDTO.getSecondPartySignType().contains("EDGE-SIGN"))) {
                    throw new DaoException("总页数大于1页必须选择骑缝!");
                }
            }
            //如果甲方信息选择了骑缝章，并且PDF页数为1， 则要报错 邓京术 2025-06-11
            if (digitalSealBusinessDTO.getFirstPartySignType().contains("EDGE-SIGN")) {//甲方签署类型：骑缝
                if (pageNumber <= 1) {
                    throw new DaoException("总页数大于1才能选择骑缝!");
                }
                SubjectDTO.SignConfigs signConfigJf = new SubjectDTO.SignConfigs();
                signConfigJf.setSignType("EDGE-SIGN");
                signConfigJf.setPageNo(digitalSealBusinessDTO.getFirstPartyPageNo());
                signConfigJf.setPosY(Integer.valueOf(digitalSealBusinessDTO.getFirstPartyEdgePosY()));
                //设置印章
                signConfigJf.setSealId(sealConfigDTOS.getSealCode());
                //指定签署印章类型：PERSON-SEAL-个人印章、COMMON-SEAL-企业授权印章、LEGAL-PERSON-SEAL-法人章
                signConfigJf.setSignatureType("COMMON-SEAL");
                //指定印章类型
                signConfigJf.setSealTypeCode("1".equals(digitalSealBusinessDTO.getFirstPartySignatureType())?"CONTRACT":"2".equals(digitalSealBusinessDTO.getFirstPartySignatureType())?"PUBLIC":"FINANCE");
//                signConfigJf.setSealTypeCode(digitalSealBusinessDTO.getFirstPartySignatureType());
//                signConfigJf.setSealTypeCode("");
                signConfigsJf.add(signConfigJf);
            }


            sealInfoJf.setSignConfigs(signConfigsJf);

            sealInfosJf.add(sealInfoJf);

            signerInfoJf.setSealInfos(sealInfosJf);
            signerInfos.add(signerInfoJf);
            //这里进行判断乙方签署是不是包含在字典配置的几个公司，是的话组需要按照甲方配置进行参数设置
            if (f) {//非单签甲方的才需要进行设置乙方签署信息
                //公共对象===========
                SubjectDTO.SignerInfos signerInfoYf = new SubjectDTO.SignerInfos();
                List<SubjectDTO.SealInfos> sealInfosYf = new ArrayList<>();
                SubjectDTO.SealInfos sealInfoYf = new SubjectDTO.SealInfos();
                List<SubjectDTO.SignConfigs> signConfigsYf = new ArrayList<>();
                //==================
                digitalSealBusinessDTO.getSecondParty(); //乙方公司代码
                digitalSealBusinessDTO.getSecondPartyName();//乙方公司名称
                if(supplierConversionCode != null && !supplierConversionCode.isEmpty()){
                    //内部公司间的交易公司代码转换
                    String convertCompanyCode = supplierConversionCode.get(digitalSealBusinessDTO.getSecondParty());
                    if(StringUtils.isNotEmpty(convertCompanyCode)){
                        DigitalSealBusinessConfig data = digitalSealBusinessConfigService.getOne(Wrappers.lambdaQuery(DigitalSealBusinessConfig.class).eq(DigitalSealBusinessConfig::getBusinessTypeCode,digitalSealBusinessDTO.getBusinessTypeCode()).last(" limit 1"));
                        DigitalSealConfigClientDTO sealConfig=  contractSignClient.selectESignDetailClient(convertCompanyCode,data.getSignatureType());
                        if (sealConfig != null ){
                            User user = userService.getOne(Wrappers.lambdaQuery(User.class).eq(User::getAccountName,sealConfig.getSignerAccount()).last(" limit 1"));
                            if (user != null){
                                sealConfig.setPhone(user.getPhone()); //乙方签署人电话
                                sealConfig.setName(user.getUsername());//乙方签署人新项目
                            }
                            //设置公司间乙方公司信息
                            signerInfoYf.setUserType(1);
                            signerInfoYf.setUserCode(sealConfig.getSignerAccount());
                            signerInfoYf.setOrganizationCode(sealConfig.getSignerOrgCode());
                            signerInfoYf.setAutoSign(digitalSealBusinessDTO.getFirstPartyAutoSign());
                            //设置 签章顺序
                            if (signOrder.equals("1")) {
                                signerInfoYf.setSignMode(0);
                                signerInfoYf.setSignNode(orderOne);
                                signerInfoYf.setSignOrder(orderOne);
                            } else if (signOrder.equals("2")) {
                                signerInfoYf.setSignMode(0);
                                signerInfoYf.setSignNode(orderTow);
                                signerInfoYf.setSignOrder(orderTow);
                            }
                            //签署任务信
                            sealInfoYf.setFileKey(signFileDTO.getFileKey());
                            if (digitalSealBusinessDTO.getSecondPartySignType().contains("KEYWORD-SIGN")) {//乙方签署类型 KEYWORD-SIGN:关键字
                                SubjectDTO.SignConfigs signConfigYf = new SubjectDTO.SignConfigs();
                                //设置印章
                                signConfigYf.setSealId(sealConfig.getSealCode());
                                signConfigYf.setSignatureType("COMMON-SEAL");
                                //设置关键字
                                SubjectDTO.KeywordInfo keywordInfoYf = new SubjectDTO.KeywordInfo();
                                keywordInfoYf.setKeywordIndex(-1);
                                keywordInfoYf.setOffsetPosX(Double.valueOf(digitalSealBusinessDTO.getSecondPartyKeywordPosX()));
                                keywordInfoYf.setOffsetPosY(Double.valueOf(digitalSealBusinessDTO.getSecondPartyKeywordPosY()));
                                keywordInfoYf.setKeyword(digitalSealBusinessDTO.getSecondPartyKeyword());
                                signConfigYf.setKeywordInfo(keywordInfoYf);
                                signConfigYf.setSignFieldType(0);
                                signConfigYf.setAllowMove(0);
                                signConfigYf.setSignType("KEYWORD-SIGN");
                                signConfigsYf.add(signConfigYf);
                            }
                            if (digitalSealBusinessDTO.getSecondPartySignType().contains("EDGE-SIGN")) {//乙方签署类型：EDGE-SIGN骑缝
                                if (pageNumber <= 1) {
                                    throw new DaoException("总页数大于1才能选择骑缝!");
                                }
                                SubjectDTO.SignConfigs signConfigYf = new SubjectDTO.SignConfigs();
                                signConfigYf.setSignType("EDGE-SIGN");
                                signConfigYf.setPageNo(digitalSealBusinessDTO.getFirstPartyPageNo());
                                signConfigYf.setPosY(Integer.valueOf(digitalSealBusinessDTO.getSecondPartyEdgePosY()));
                                //设置印章
                                signConfigYf.setSealId(sealConfig.getSealCode());
                                signConfigYf.setSignatureType("COMMON-SEAL");
                               // signerInfoYf.setSealTypeCode("1".equals(digitalSealBusinessDTO.getSecondPartySignatureType())?"CONTRACT":"2".equals(digitalSealBusinessDTO.getSecondPartySignatureType())?"PUBLIC":"FINANCE");
                                signConfigsYf.add(signConfigYf);
                            }
                        }
                    }else{
                        //外部供应商组装代码
                        signerInfoYf.setUserType(2);
                        signerInfoYf.setUserCode(digitalSealBusinessDTO.getSecondPartyPhone());
                        signerInfoYf.setCustomOrgNo(digitalSealBusinessDTO.getSecondParty());
                        //指定印章类型
                        signerInfoYf.setSealTypeCode("1".equals(digitalSealBusinessDTO.getSecondPartySignatureType())?"CONTRACT":"2".equals(digitalSealBusinessDTO.getSecondPartySignatureType())?"PUBLIC":"FINANCE");
//                signerInfoYf.setSealTypeCode("");

                        if (signOrder.equals("1")) {
                            signerInfoYf.setSignMode(0);
                            signerInfoYf.setSignNode(orderOne);
                            signerInfoYf.setSignOrder(orderOne);
                        } else if (signOrder.equals("2")) {
                            signerInfoYf.setSignMode(0);
                            signerInfoYf.setSignNode(orderTow);
                            signerInfoYf.setSignOrder(orderTow);
                        }
//            签署任务信
                        sealInfoYf.setFileKey(signFileDTO.getFileKey());
                        if (digitalSealBusinessDTO.getSecondPartySignType().contains("KEYWORD-SIGN")) {//乙方签署类型 KEYWORD-SIGN:关键字
                            SubjectDTO.SignConfigs signConfigYf = new SubjectDTO.SignConfigs();
                            signConfigYf.setSignatureType("COMMON-SEAL");
                            //设置关键字
                            SubjectDTO.KeywordInfo keywordInfoYf = new SubjectDTO.KeywordInfo();
                            keywordInfoYf.setKeywordIndex(-1);
                            keywordInfoYf.setOffsetPosX(Double.valueOf(digitalSealBusinessDTO.getSecondPartyKeywordPosX()));
                            keywordInfoYf.setOffsetPosY(Double.valueOf(digitalSealBusinessDTO.getSecondPartyKeywordPosY()));
                            keywordInfoYf.setKeyword(digitalSealBusinessDTO.getSecondPartyKeyword());
                            signConfigYf.setKeywordInfo(keywordInfoYf);
                            signConfigYf.setSignFieldType(0);
                            signConfigYf.setAllowMove(0);
                            signConfigYf.setSignType("KEYWORD-SIGN");
                            signConfigsYf.add(signConfigYf);
                        }
                        if (digitalSealBusinessDTO.getSecondPartySignType().contains("EDGE-SIGN")) {//乙方信息签署类型：EDGE-SIGN骑缝
                            if (pageNumber <= 1) {
                                throw new DaoException("总页数大于1才能选择骑缝!");
                            }
                            SubjectDTO.SignConfigs signConfigYf = new SubjectDTO.SignConfigs();
                            signConfigYf.setSignType("EDGE-SIGN");
                            signConfigYf.setPageNo(digitalSealBusinessDTO.getFirstPartyPageNo());
                            signConfigYf.setPosY(Integer.valueOf(digitalSealBusinessDTO.getSecondPartyEdgePosY()));
                            //设置印章
//                    signConfigYf.setSealId(sealConfigDTOS.getSealCode());
                            //指定签署印章类型：PERSON-SEAL-个人印章、COMMON-SEAL-企业授权印章、LEGAL-PERSON-SEAL-法人章
                            signConfigYf.setSignatureType("COMMON-SEAL");
                            signConfigsYf.add(signConfigYf);
                        }
                    }
                }
                //公用代码
                sealInfoYf.setSignConfigs(signConfigsYf);
                sealInfosYf.add(sealInfoYf);
                signerInfoYf.setSealInfos(sealInfosYf);
                signerInfos.add(signerInfoYf);
            }

            subjectDTO.setSignerInfos(signerInfos);

            // 请求Body体数据
            String reqBodyData = JSONObject.toJSONString(subjectDTO);
            log.info("发起签署流程接口调用参数{}", reqBodyData);
            System.out.println("请求信息： " + reqBodyData);

            // 构建参与请求签名计算的明文
            String plaintext = reqBodyData;
            // 计算请求签名值
            String reqSignature = SignUtils.sign256(plaintext, projectsecret);
            // 构建请求头

            LinkedHashMap<String, String> header = new LinkedHashMap<>();
            // 构建待签名字符串
            String contentType = "application/json; charset=UTF-8";
            String accept = "*/*";
            header.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)");
            header.put("X-timevale-signature", reqSignature);
            header.put("X-timevale-project-id", projectid);
            header.put("Accept", accept);
            header.put("Content-Type", contentType);
            header.put("Content-Length", "1123");

            String getInnerOrganizationsDetailApi = "/esign-signs/v1/signFlow/createAndStart";
            String uploadApiUrl = serverip + getInnerOrganizationsDetailApi;
            //发送POST请求
            String result = null;
            try {
                result = HTTPHelper.sendPOST1(uploadApiUrl, reqBodyData, header, "UTF-8");
                log.info("发起签署流程接口返回结果{}", JSON.toJSONString(result));
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                //调用方日志
                LogManager.me().executeLog(ApiLogTaskFactory.saveCallLog("sendSignFile", "一步发起签署接口",
                        ThirdSysType.SIGN.getType(),
                        reqBodyData,
                        result,
                        "",
                        LocalDateTime.now()
                ));
            }
            System.out.println(JSON.toJSONString("result----" + result));
            ApiResult json = JSON.parseObject(result, ApiResult.class);
            if (json.getCode().equals(RestCode.MES_SUCCESS.getCode())) {
                JSONObject dataJson = (JSONObject) json.getData();
                DigitalSealBusinessDetail detail = digitalSealBusinessDetailConvert.DTO2Entity(digitalSealBusinessDTO);
                detail.setFileId(signFileDTO.getFileId());
                detail.setFileKey(signFileDTO.getFileKey());
                detail.setSignFlowId(dataJson.getString("signFlowId"));
                detail.setSignStatus(dataJson.getInteger("signFlowStatus"));
                detail.setCreateTime(LocalDateTime.now());
                digitalSealBusinessDetails.add(detail);

//                return ContractSendSignResultDTO.builder().signFlowId(dataJson.getString("signFlowId"))
//                .signFlowStatus(dataJson.getString("signFlowStatus")).build();

                if (CollectionUtils.isNotEmpty(idList)) {
                    //处理逻辑
                    for (Long id : idList) {
                        DigitalSealBusinessDetail newDetail = new DigitalSealBusinessDetail();
                        BeanUtils.copyProperties(detail,newDetail);
                        newDetail.setBusinessId(id);
                        digitalSealBusinessDetails.add(newDetail);
                    }
                }

                //2024-08-19,如果是对账单文件发起签署成功后，删除之前的对账签署文件
                if("account_statement".equals(digitalSealBusinessDTO.getBusinessTypeCode()) && Objects.nonNull(digitalSealBusinessDTO.getBusinessId())){
                    digitalSealBusinessDetailService.remove(Wrappers.lambdaQuery(DigitalSealBusinessDetail.class).eq(DigitalSealBusinessDetail::getBusinessId,digitalSealBusinessDTO.getBusinessId()).eq(DigitalSealBusinessDetail::getBusinessTypeCode,"account_statement"));
                }

                if("purchase_sale_contract".equals(digitalSealBusinessDTO.getBusinessTypeCode()) && Objects.nonNull(digitalSealBusinessDTO.getBusinessId())){
                    digitalSealBusinessDetailService.remove(Wrappers.lambdaQuery(DigitalSealBusinessDetail.class).eq(DigitalSealBusinessDetail::getBusinessId,digitalSealBusinessDTO.getBusinessId()).eq(DigitalSealBusinessDetail::getBusinessTypeCode,"purchase_sale_contract"));
                }


            } else {
                FileResposeDTO fileResposeDTO = fileLogic.getForDownload(signFileDTO.getFileId());
                throw new DaoException(StrUtil.format("文件：{}，e签宝接口返回错误：{}", fileResposeDTO.getFileName(),
                        json.getMessage()));
            }
        }



        if (CollectionUtils.isNotEmpty(digitalSealBusinessDetails)) {
            digitalSealBusinessDetailService.saveBatch(digitalSealBusinessDetails);
        }

        //修改采购订单的财务确认状态为未确认
        if("purchase_order".equals(digitalSealBusinessDTO.getBusinessTypeCode()) && CollectionUtils.isNotEmpty(digitalSealBusinessDetails)){
            List<Long> collectList = digitalSealBusinessDetails.stream().map(DigitalSealBusinessDetail::getBusinessId).collect(Collectors.toList());
            purchaseOrderClient.updateOrderFinAndFileState(collectList,FlagConst.N.getCode(),null);
        }

    }

    @Override
    public List<DigitalSealBusinessDetailDTO> fileList(Long businessId, String businessTypeCode,String signOrder,Integer notShowDelete) {
        List<String> businessTypeCodeList = Arrays.asList(StringUtils.split(businessTypeCode, ","));
        LambdaQueryWrapper<DigitalSealBusinessDetail> queryWrapper = Wrappers.lambdaQuery(DigitalSealBusinessDetail.class)
                .eq(DigitalSealBusinessDetail::getBusinessId, businessId)
                .in(DigitalSealBusinessDetail::getBusinessTypeCode, businessTypeCodeList);
        if (notShowDelete != null&& notShowDelete == 1){
            //queryWrapper.ne(DigitalSealBusinessDetail::getSignStatus, 7);
            queryWrapper.eq(DigitalSealBusinessDetail::getSignStatus, 2);//只取签署完成的附件
        }
        if (StrUtil.isNotEmpty(signOrder)){
            List<String> signOrderList = Arrays.asList(StringUtils.split(signOrder, ","));

            queryWrapper.and(wrapper -> wrapper.in(DigitalSealBusinessDetail::getSignOrder, signOrderList).or()
                    .isNull(DigitalSealBusinessDetail::getSignOrder).or()
                    .eq(DigitalSealBusinessDetail::getSignOrder,""));
        }
        List<DigitalSealBusinessDetail> digitalSealBusinessDetails = digitalSealBusinessDetailService.list(queryWrapper);
        return digitalSealBusinessDetailConvert.entity2DTOList(digitalSealBusinessDetails);
    }

    @Override
    public Boolean checkList(Long businessId) {
        List<DigitalSealBusinessDetail> digitalSealBusinessDetails = digitalSealBusinessDetailService.list(
                Wrappers.lambdaQuery(DigitalSealBusinessDetail.class)
                        .eq(DigitalSealBusinessDetail::getBusinessId, businessId));
        return CollectionUtils.isNotEmpty(digitalSealBusinessDetails);
    }

    @Override
    public ApiResult callBack(SignBackDTO signBackDTO) {
        //0草稿，1签署中，2完成，3已过期，4已拒签，5已作废，6作废中
//        DigitalSealBusinessDetail contract = digitalSealBusinessDetailService.getOne(
//                new LambdaQueryWrapper<DigitalSealBusinessDetail>().eq(DigitalSealBusinessDetail::getSignFlowId,
//                        signBackDTO.getCallBackProcessVO().processId));
//        if (Objects.isNull(contract)) {
//            throw new DaoException("未找到匹配流程!");
//        }
        //20240814qzc

        List<DigitalSealBusinessDetail> contractList = digitalSealBusinessDetailService.list(new LambdaQueryWrapper<DigitalSealBusinessDetail>().eq(DigitalSealBusinessDetail::getSignFlowId,
                signBackDTO.getCallBackProcessVO().processId));
        if (CollectionUtils.isEmpty(contractList)) {
            throw new DaoException("未找到匹配流程!");
        }
        for (DigitalSealBusinessDetail contract : contractList) {
            contract.setSignStatus(signBackDTO.getCallBackProcessVO().flowStatus);
            // 已完成 下载文件
            if (signBackDTO.getCallBackProcessVO().flowStatus == SignFlowStatus.Completed.getStatus()) {
                final Pair<String, String> defaultFileAbsolutePath = fileLogic.genDatePath();
                String signDownloadOuterUrl = "";
                if (signBackDTO.getCallBackProcessVO().flowStatus == SignFlowStatus.Completed.getStatus()) {
                    List<SignBackDTO.SignerList> signFileLists = signBackDTO.getCallBackProcessVO().getSignerList();
                    if (signFileLists != null && signFileLists.size() == 1) {
                        signDownloadOuterUrl = signFileLists.get(0).getSignFileList().get(0).getSignedFileKey();
                    } else {
                        Map<Integer, List<SignBackDTO.SignerList>> maps = signFileLists.stream()
                                .collect(Collectors.groupingBy(SignBackDTO.SignerList::getSignOrder));
                        signDownloadOuterUrl = maps.get(2).get(0).getSignFileList().get(0).getSignedFileKey();
                    }
                }
                String path = SignUtils.getFile(signDownloadOuterUrl, defaultFileAbsolutePath, serverip,
                        "/file/v1/getDownloadUrl",
                        projectsecret, projectid);
                if (StringUtils.isNotEmpty(path)) {
                    // 读取文件内容
                    Path pathFile = Paths.get(path);
                    final File file = pathFile.toFile();
                    FileResposeDTO fileResposeCDTO = fileLogic.saveSignFile(file);
                    if (!Objects.isNull(fileResposeCDTO)) {
                        contract.setFileId(fileResposeCDTO.getId());
                    }
                }
                //需要判断然后更新订单数据
                if (contract.getBusinessTypeCode().equals(SignProcessType.PURCHASE_ORDER.getBusinessNo())) {
                    if (!contract.getSignOrder().equals("3")) {
                        purchaseOrderClient.updateOrderFin(contract.getBusinessId());
                    }
                }
            }
            digitalSealBusinessDetailService.updateById(contract);
        }


        return ApiResult.builder().code(RestCode.SIGN_SUCCESS.getCode()).build();
    }

    @Override
    public ESignOutOrgResult saveOutOrgWithUser(ESignOutOrgParamDTO signBackDTO) {
        // 请求Body体数据
        String reqBodyData = JSONObject.toJSONString(signBackDTO);
        log.info("推送外部组织和用户参数{}", reqBodyData);
        // 构建参与请求签名计算的明文
        String plaintext = reqBodyData;
        // 计算请求签名值
        String reqSignature = SignUtils.sign256(plaintext, projectsecret);
        // 构建请求头

        LinkedHashMap<String, String> header = new LinkedHashMap<>();
        // 构建待签名字符串
        String contentType = "application/json; charset=UTF-8";
        String accept = "*/*";
        header.put("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)");
        header.put("X-timevale-signature", reqSignature);
        header.put("X-timevale-project-id", projectid);
        header.put("Accept", accept);
        header.put("Content-Type", contentType);

        String getInnerOrganizationsDetailApi = "/manage/v1/outerOrganizations/createWithUser";
        String uploadApiUrl = serverip + getInnerOrganizationsDetailApi;
        //发送POST请求
        String result = null;
        try {
            result = HTTPHelper.sendPOST1(uploadApiUrl, reqBodyData, header, "UTF-8");
            final ApiResult apiResult = JSON.parseObject(result, ApiResult.class);
            if (apiResult.getCode().equals("200")) {
                final String jsonString = JSON.toJSONString(apiResult.getData());
                return JSON.parseObject(jsonString, ESignOutOrgResult.class);
            } else {
                throw new DaoException(apiResult.getMessage());
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            //调用方日志
            LogManager.me().executeLog(ApiLogTaskFactory.saveCallLog("sendSignFile", "推送外部组织和用户接口",
                    ThirdSysType.SIGN.getType(),
                    reqBodyData,
                    result,
                    "",
                    LocalDateTime.now()
            ));
        }
    }

    @Override
    public void remove(Long id, String deleteRemark) {
        //通过id查找相同 sign_flow_id
        DigitalSealBusinessDetail digitalSealBusinessDetail = digitalSealBusinessDetailService.getById(id);
        if(StringUtils.isNotEmpty(digitalSealBusinessDetail.getSignFlowId())){
            List<DigitalSealBusinessDetail> digitalSealBusinessDetails = digitalSealBusinessDetailService.list(new LambdaQueryWrapper<DigitalSealBusinessDetail>().eq(DigitalSealBusinessDetail::getSignFlowId,
                    digitalSealBusinessDetail.getSignFlowId()).ne(DigitalSealBusinessDetail::getSignStatus,7));
            if(CollectionUtils.isNotEmpty(digitalSealBusinessDetails)){
                List<DigitalSealBusinessDetail> updateDetails = new ArrayList<>();
                for (DigitalSealBusinessDetail sealBusinessDetail : digitalSealBusinessDetails) {
                    DigitalSealBusinessDetail detail = new DigitalSealBusinessDetail();
                    detail.setId(sealBusinessDetail.getId());
                    detail.setDeleteRemark(deleteRemark);
                    detail.setSignStatus(7);
                    detail.setUpdateTime(LocalDateTime.now());
                    detail.setUpdateUser(LoginUtil.getUserId());
                    updateDetails.add(detail);
                }
                if(CollectionUtils.isNotEmpty(updateDetails)){
                    digitalSealBusinessDetailService.updateBatchById(updateDetails);
                }
                //2024-08-16
                //1.双签逻辑：如果是采购订单，则需要判断该批次里面的所有订单是否存在签署中的文件，如果存在则需要修改财务确认标识，
                //2.双签逻辑： 如果文件删除完，则回签状态改为否
                //财务确认状态和回签状态可以同步修改
                List<Long> businessList = digitalSealBusinessDetails.stream().filter(entity -> "purchase_order".equals(entity.getBusinessTypeCode())).map(DigitalSealBusinessDetail::getBusinessId).collect(Collectors.toList());
                if(CollectionUtils.isNotEmpty(businessList)){
                    //2024-09-19
                    List<DigitalSealBusinessDetail> dbDetailList = digitalSealBusinessDetailService.list(new LambdaQueryWrapper<DigitalSealBusinessDetail>()
                            .in(DigitalSealBusinessDetail::getSignStatus,Arrays.asList(1,2))
                            .eq(DigitalSealBusinessDetail::getBusinessTypeCode,"purchase_order")
                            .ne(DigitalSealBusinessDetail::getSignStatus,7)
                            .in(DigitalSealBusinessDetail::getBusinessId,businessList));
                    //1.全部附件都被删除了
                    if(CollectionUtils.isEmpty(dbDetailList)){
                        purchaseOrderClient.updateOrderFinAndFileState(businessList, FlagConst.N.getCode(),FlagConst.N.getCode());
                    }else{
                        List<DigitalSealBusinessDetail> collect = dbDetailList.stream().filter(detail -> detail.getSignOrder().equals("1") || detail.getSignOrder().equals("2")).collect(Collectors.toList());
                        List<DigitalSealBusinessDetail> singleCollect = dbDetailList.stream().filter(detail -> detail.getSignOrder().equals("3")).collect(Collectors.toList());
                        if(CollectionUtils.isNotEmpty(collect) && CollectionUtils.isEmpty(singleCollect)){
                            //2.单签甲方文件已经全部删除，存在双签签署中的文件则将财务确认状态改成未确认，否则不修改
                            boolean containsStatusOne = collect.stream().anyMatch(detail -> detail.getSignStatus() == 1);
                           if(containsStatusOne){
                               purchaseOrderClient.updateOrderFinAndFileState(businessList, FlagConst.N.getCode(),FlagConst.N.getCode());
                           }
                        }

                    }



//                    //甲方单签采购订单
//                    if(digitalSealBusinessDetail.getSignOrder().equals("3") && digitalSealBusinessDetail.getBusinessTypeCode().equals("purchase_order")){
//                        //单签文件全部删除完，需要修改财务确认状态改为未确认以及回签状态改为否
//                        List<DigitalSealBusinessDetail> dqDetailList = digitalSealBusinessDetailService.list(new LambdaQueryWrapper<DigitalSealBusinessDetail>().in(DigitalSealBusinessDetail::getSignStatus,
//                                        Arrays.asList(1,2)).eq(DigitalSealBusinessDetail::getBusinessTypeCode,"purchase_order").eq(DigitalSealBusinessDetail::getSignOrder,3)
//                                .in(DigitalSealBusinessDetail::getBusinessId,businessList));
//                        if(CollectionUtils.isEmpty(dqDetailList)){
//                            purchaseOrderClient.updateOrderFinAndFileState(businessList, FlagConst.N.getCode(),FlagConst.N.getCode());
//                        }
//                    }else if(!digitalSealBusinessDetail.getSignOrder().equals("3") && digitalSealBusinessDetail.getBusinessTypeCode().equals("purchase_order")){
//                      //双签采购订单
//                        //双签存在签署中的，单签甲方不存在签署中的状态
//                        List<DigitalSealBusinessDetail> businessDetails = digitalSealBusinessDetailService.list(new LambdaQueryWrapper<DigitalSealBusinessDetail>().eq(DigitalSealBusinessDetail::getSignStatus,
//                                        1).eq(DigitalSealBusinessDetail::getBusinessTypeCode,"purchase_order")
//                                .ne(DigitalSealBusinessDetail::getSignOrder,3)
//                                .in(DigitalSealBusinessDetail::getBusinessId,businessList));
//                        if(CollectionUtils.isNotEmpty(businessDetails)){
//                            //修改采购订单财务确认状态为未确认 和 回签状态为是
//                            purchaseOrderClient.updateOrderFinAndFileState(businessList, FlagConst.N.getCode(), FlagConst.Y.getCode());
//                        }
//                        //双签全部为删除状态
//                        List<DigitalSealBusinessDetail> detailList = digitalSealBusinessDetailService.list(new LambdaQueryWrapper<DigitalSealBusinessDetail>().in(DigitalSealBusinessDetail::getSignStatus,
//                                        Arrays.asList(1,2)).eq(DigitalSealBusinessDetail::getBusinessTypeCode,"purchase_order").ne(DigitalSealBusinessDetail::getSignStatus,7)
//                                .in(DigitalSealBusinessDetail::getBusinessId,businessList));
//                        //查询该批次文件状态如果为删除状态 修改回签状态为否 sign_order == 3 单签甲方
//                        if(CollectionUtils.isEmpty(detailList)){
//                            purchaseOrderClient.updateOrderFinAndFileState(businessList,FlagConst.N.getCode(),FlagConst.N.getCode());
//                         //   purchaseOrderClient.updateOrderFileState(businessList);
//                        }
//                    }
                }
            }
        }else{
            DigitalSealBusinessDetail detail = new DigitalSealBusinessDetail();
            detail.setId(id);
            detail.setDeleteRemark(deleteRemark);
            detail.setSignStatus(7);
            digitalSealBusinessDetailService.updateById(detail);
        }
    }

    @Override
    public List<DigitalSealBusinessDetailDTO> fileListByStatus(String businessIds, String businessTypeCode,
                                                               Integer signStatus)
    {

        List<DigitalSealBusinessDetail> digitalSealBusinessDetails = digitalSealBusinessDetailService.list(
                Wrappers.lambdaQuery(DigitalSealBusinessDetail.class)
                        .in(DigitalSealBusinessDetail::getBusinessId,
                                Arrays.asList(StringUtils.split(businessIds, ",")))
                        .eq(DigitalSealBusinessDetail::getBusinessTypeCode, businessTypeCode)
                        .eq(DigitalSealBusinessDetail::getSignStatus, signStatus)
        );
        return digitalSealBusinessDetailConvert.entity2DTOList(digitalSealBusinessDetails);
    }
}
