package com.malk.jinlun.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.google.gson.Gson;
import com.kingdee.bos.webapi.entity.IdentifyInfo;
import com.kingdee.bos.webapi.entity.RepoRet;
import com.kingdee.bos.webapi.sdk.K3CloudApi;
import com.malk.jinlun.config.KDWebApiConf;
import com.malk.jinlun.entity.*;
import com.malk.jinlun.mapper.JinlunMapper;
import com.malk.jinlun.service.CpClient;
import com.malk.jinlun.service.JinlunService;
import com.malk.server.common.McR;
import com.malk.server.teambition.TBConf;
import com.malk.server.teambition.TBR;
import com.malk.utils.PublicUtil;
import com.malk.utils.UtilHttp;
import com.malk.utils.UtilMap;
import com.malk.utils.UtilToken;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.net.CookieManager;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.util.*;

import static org.junit.Assert.fail;

@Slf4j
@Service
public class JinlunServiceImpl implements JinlunService {
    @Autowired
    private KDWebApiConf kdWebApiConf;

    @Autowired
    private CpClient cpClient;

    @Autowired
    private TBConf tbConf;

    @Autowired
    private JinlunMapper jinlunMapper;

    private final Object $lock = new Object[0];

    private static final Long EXPIRES_IN = 7200000L;

    @Override
    public McR addCustomer(@RequestBody Map map) {
        //查询云枢客户单据详情
        String objectId = UtilMap.getString(map, "objectId");

        Map customer = cpClient.getCpBo("ZLKHLC", objectId, null);

        Map data = UtilMap.getMap(customer, "data");

        Map bizObject = UtilMap.getMap(data, "bizObject");

        Map customerData = UtilMap.getMap(bizObject, "data");

        //请求参数，要求为json字符串
        Save save = new Save();
        CustomerModel customerModel = new CustomerModel();

        //基本信息
        String FName = UtilMap.getString(customerData,"ShortText1758195928433");//客户名称
        String FShortName = UtilMap.getString(customerData,"ShortText1758195937324");//客户简称
        FNumber FCOUNTRY = new FNumber(UtilMap.getString(customerData,"ShortText1760000048047"));//国家
        FNumber FGroup = new FNumber(UtilMap.getString(customerData,"Dropdown1758198564777_key"));//客户分组
        String F_VMKV_Combo = UtilMap.getString(customerData,"Dropdown1758198576644_key");//客户等级
        FNumber FCustTypeId = new FNumber(UtilMap.getString(customerData,"Dropdown1758196678786_key"));//客户类别
        String FDescription = UtilMap.getString(customerData,"LongText1758198621716");//备注

        //商务信息
        FNumber FSELLER = new FNumber(UtilMap.getString(customerData,"ShortText1759997501370"));//销售员
        FSTAFFNUMBER F_VMKV_Base1 = new FSTAFFNUMBER(UtilMap.getString(customerData,"Text1762059270203"));//跟单员
        FNumber FRECCONDITIONID = new FNumber(UtilMap.getString(customerData,"Dropdown1758199217950_key"));//收款条件
        FNumber FTRADINGCURRID = new FNumber(UtilMap.getString(customerData,"Dropdown1758199184443_key"));//结算币别
        FNumber FSETTLETYPEID = new FNumber(UtilMap.getString(customerData,"Dropdown1758199160962_key"));//结算方式
        FNumber FTaxRate = new FNumber(UtilMap.getString(customerData,"Dropdown1758199231927_key"));//税率
        FNumber FTaxType = new FNumber(UtilMap.getString(customerData,"Dropdown1758199263660_key"));//税分类
        String FInvoiceType = UtilMap.getString(customerData,"Dropdown1758199247249_key");//发票类型
        Boolean FISCREDITCHECK = UtilMap.getBoolean(customerData,"Logic1758199516570");//启用信用管理
        String F_VMKV_Combo1 = UtilMap.getString(customerData,"Dropdown1762058555728_key");//订单要求

        //开票信息
        String FINVOICEBANKACCOUNT = UtilMap.getString(customerData,"ShortText1758199605057");//银行账号
        String FINVOICETITLE = UtilMap.getString(customerData,"ShortText1758199610851");//发票抬头
        String FTAXREGISTERCODE = UtilMap.getString(customerData,"ShortText1758199617057");//纳税登记号
        String FINVOICEBANKNAME = UtilMap.getString(customerData,"Text1758199624533");//开户银行
        String FSOCIALCRECODE  = UtilMap.getString(customerData,"Text1758199630373");//统一社会信用代码
        String FINVOICETEL = UtilMap.getString(customerData,"Text1758199637444");//开票联系电话
        String FINVOICEADDRESS = UtilMap.getString(customerData,"LongText1758199679685");//开票通讯地址

        //地址信息
        List<Map> addressList = UtilMap.getList(customerData, "Sheet1758199794948");
        List<CustomerContactEntry> FT_BD_CUSTCONTACT = new ArrayList<>();

        for (Map address : addressList) {
            CustomerContactEntry customerContactEntry = new CustomerContactEntry();
            String addressCode = UtilMap.getString(address, "ShortText1758199808715");
            String addressName = UtilMap.getString(address, "ShortText1758199824395");

            if (Strings.isNotBlank(addressCode) && Strings.isNotBlank(addressName)){
                customerContactEntry.setFNUMBER1(addressCode);//地点编码
                customerContactEntry.setFNAME1(addressName);//地点名称

                FT_BD_CUSTCONTACT.add(customerContactEntry);
            }
        }

        customerModel.setFName(FName);
        customerModel.setFShortName(FShortName);
        customerModel.setFCOUNTRY(FCOUNTRY);
        customerModel.setFGroup(FGroup);
        customerModel.setF_VMKV_Combo(F_VMKV_Combo);
        customerModel.setFCustTypeId(FCustTypeId);
        customerModel.setFDescription(FDescription);
        customerModel.setFSELLER(FSELLER);
        customerModel.setF_VMKV_Base1(F_VMKV_Base1);
        customerModel.setFRECCONDITIONID(FRECCONDITIONID);
        customerModel.setFTRADINGCURRID(FTRADINGCURRID);
        customerModel.setFSETTLETYPEID(FSETTLETYPEID);
        customerModel.setFTaxRate(FTaxRate);
        customerModel.setFTaxType(FTaxType);
        customerModel.setFInvoiceType(FInvoiceType);
        customerModel.setFISCREDITCHECK(FISCREDITCHECK);
        customerModel.setF_VMKV_Combo1(F_VMKV_Combo1);
        customerModel.setFINVOICEBANKACCOUNT(FINVOICEBANKACCOUNT);
        customerModel.setFINVOICETITLE(FINVOICETITLE);
        customerModel.setFTAXREGISTERCODE(FTAXREGISTERCODE);
        customerModel.setFINVOICEBANKNAME(FINVOICEBANKNAME);
        customerModel.setFSOCIALCRECODE(FSOCIALCRECODE);
        customerModel.setFINVOICETEL(FINVOICETEL);
        customerModel.setFINVOICEADDRESS(FINVOICEADDRESS);

        if (!FT_BD_CUSTCONTACT.isEmpty()){
            customerModel.setFT_BD_CUSTCONTACT(FT_BD_CUSTCONTACT);
        }

        save.setModel(customerModel);
        Gson gson2 = new Gson();
        String jsonData = gson2.toJson(save);

        log.info(jsonData);

        K3CloudApi client = new K3CloudApi(initIden());
        //业务对象标识
        String formId = "BD_Customer";
        //调用接口
        String resultJson = "";
        try {
            resultJson = client.save(formId,jsonData);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        //用于记录结果
        Gson gson = new Gson();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);

        String customerCode = "";

        if (isTrue(repoRet)){
            String id = repoRet.getResult().getId();
            Submit submit = new Submit();
            submit.setIds(id);
            //提交客户
            String resultJson2 = "";
            try {
                resultJson2 = client.submit(formId, JSONObject.toJSONString(submit));
            }catch (Exception e){
                throw new RuntimeException(e);
            }
            RepoRet repoRet2 = gson.fromJson(resultJson2, RepoRet.class);
            isTrue(repoRet2);
            customerCode = repoRet2.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();
            //回写云枢客户编号
//            cpClient.updateCpBo("ZLKHLC",UtilMap.map("id, ShortText1758195840127",objectId,customerCode),null);

            if (isTrue(repoRet2)){
                Audit audit = new Audit();
                audit.setNumbers(Arrays.asList(customerCode));
                //审核客户
                String resultJson3 = "";
                try {
                    resultJson3 = client.audit(formId,JSONObject.toJSONString(audit));
                }catch (Exception e){
//                    throw new RuntimeException(e);
                    e.printStackTrace();
                    log.error(e.getMessage());
                }

                RepoRet repoRet3 = gson.fromJson(resultJson3, RepoRet.class);
//                isTrue(repoRet3);
            }
        }


        return McR.success(customerCode);
    }

    @Async
    @Override
    public void addCustomerContact(Map map) {
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        //请求参数，要求为json字符串
        Save save = new Save();
        ContactModel contactModel = new ContactModel();

        String objectId = UtilMap.getString(map, "objectId");

        Map contact = cpClient.getCpBo("JL002", objectId, null);

        Map cpBoResultData = cpClient.getCpBoResultData(contact);

        String FName = UtilMap.getString(cpBoResultData, "ShortText1757918028530");//联系人姓名
        String FMobile = UtilMap.getString(cpBoResultData, "ShortText1760076219303");//移动电话
        FNumber Fex = new FNumber(UtilMap.getString(cpBoResultData, "Radio1757922932185_key"));//性别
        String FPost = UtilMap.getString(cpBoResultData, "ShortText1757918203180");//职务
        String FCompanyType = "BD_Customer";//类型：客户
        String FTel = UtilMap.getString(cpBoResultData, "ShortText1757922962403");//固定电话
        String FFax = UtilMap.getString(cpBoResultData, "ShortText1757918148867");//传真
        String FEmail = UtilMap.getString(cpBoResultData, "ShortText1757918154124");//邮箱
        FNumber FCustId = new FNumber(UtilMap.getString(cpBoResultData, "ShortText1758159321906"));//客户编码

        contactModel.setFName(FName);
        contactModel.setFMobile(FMobile);
        contactModel.setFex(Fex);
        contactModel.setFPost(FPost);
        contactModel.setFCompanyType(FCompanyType);
        contactModel.setFTel(FTel);
        contactModel.setFFax(FFax);
        contactModel.setFEmail(FEmail);
        contactModel.setFCustId(FCustId);

        save.setModel(contactModel);

        Gson gson2 = new Gson();
        String jsonData = gson2.toJson(save);

        log.info(jsonData);

        K3CloudApi client = new K3CloudApi(initIden());
        //业务对象标识
        String formId = "BD_CommonContact";
        //调用接口
        String resultJson = "";
        try {
            resultJson = client.save(formId,jsonData);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        //用于记录结果
        Gson gson = new Gson();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);

        isTrue(repoRet);

        String contactCode = repoRet.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();

        cpClient.updateCpBo("JL002",UtilMap.map("id, ShortText1760075793733",objectId,contactCode),null);
    }

    @Async
    @Override
    public void updateCustomer(Map map) {
        K3CloudApi client = new K3CloudApi(initIden());
        //业务对象标识
        String formId = "BD_Customer";

        //查询云枢客户详情
        String objectId = UtilMap.getString(map, "objectId");
        Map customer = cpClient.getCpBo("KHDA", objectId, null);
        Map customerData = cpClient.getCpBoResultData(customer);

        String custFNumber = UtilMap.getString(customerData, "ShortText1758195840127");//客户编码
        FNumber FSELLER = new FNumber(UtilMap.getString(customerData, "ShortText1759998244839"));//销售负责人

        //反审核
        UnAudit unAudit = new UnAudit();
        unAudit.setNumbers(Arrays.asList(custFNumber));//客户编码

        RepoRet repoRet = new RepoRet();

        try {
            String resultJson = client.unAudit(formId,new Gson().toJson(unAudit));
            repoRet = new Gson().fromJson(resultJson, RepoRet.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        isTrue(repoRet);

        //查询客户内码
        View view = new View();
        view.setNumber(custFNumber);//客户编码

        RepoRet repoRet2 = new RepoRet();

        try {
            String resultJson = client.view(formId,new Gson().toJson(view));
            repoRet2 = new Gson().fromJson(resultJson, RepoRet.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        isTrue(repoRet2);

        int FCUSTID = UtilMap.getDouble((Map) repoRet2.getResult().getResult(), "Id").intValue();

        //保存
        Save save = new Save();
        CustomerModel customerModel = new CustomerModel();
        customerModel.setFCUSTID(FCUSTID);//客户内码
        customerModel.setFSELLER(FSELLER);//销售员
        save.setModel(customerModel);
        save.setNeedUpDateFields(Arrays.asList("FSELLER"));

        RepoRet repoRet3 = new RepoRet();

        try {
            String resultJson = client.save(formId,new Gson().toJson(save));
            repoRet3 = new Gson().fromJson(resultJson, RepoRet.class);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        isTrue(repoRet3);

        //提交
        Submit submit = new Submit();
        submit.setNumbers(Arrays.asList(custFNumber));//客户编码

        RepoRet repoRet4 = new RepoRet();

        try {
            String resultJson = client.submit(formId, JSONObject.toJSONString(submit));
            repoRet4 = new Gson().fromJson(resultJson, RepoRet.class);
        }catch (Exception e){
            throw new RuntimeException(e);
        }

        isTrue(repoRet4);

        //审核
        Audit audit = new Audit();
        audit.setNumbers(Arrays.asList(custFNumber));

        RepoRet repoRet5 = new RepoRet();

        try {
            String resultJson = client.audit(formId,JSONObject.toJSONString(audit));
            repoRet5 = new Gson().fromJson(resultJson, RepoRet.class);
        }catch (Exception e){
            throw new RuntimeException(e);
        }

        isTrue(repoRet5);
    }

    @Override
    public McR addSaleOrder(Map map) {
        //查询云枢客户单据详情
        String objectId = UtilMap.getString(map, "objectId");

        Map saleOrder = cpClient.getCpBo("XSDD", objectId, null);

        Map saleOrderData = cpClient.getCpBoResultData(saleOrder);

        //请求参数，要求为json字符串
        Save save = new Save();
        SaleOrderModel saleOrderModel = new SaleOrderModel();

        //基本信息
        FNumber FBillTypeID = new FNumber(UtilMap.getString(saleOrderData, "Dropdown1758339062589_key"));//单据类型
        String FDate = UtilMap.getString(saleOrderData, "Date1758339215935");//日期
        FNumber FCustId = new FNumber(UtilMap.getString(saleOrderData, "ShortText1760426148831"));//客户
        String F_NLD_DDTYPE = UtilMap.getString(saleOrderData, "Dropdown1758340059699_key");//订单类型
        FNumber FSalerId = new FNumber(UtilMap.getString(saleOrderData, "ShortText1760421121913"));//销售员
        FSTAFFNUMBER F_Sl_gendanyuan = new FSTAFFNUMBER(UtilMap.getString(saleOrderData, "Text1760421147555"));//跟单员
        String FBusinessType = UtilMap.getString(saleOrderData,"Dropdown1758339265813_key");//业务类型
        String F_WGR_Combo_re5 = UtilMap.getString(saleOrderData,"Dropdown1758340112723_key");//订单要求
        FNumber FHEADLOCID = new FNumber(UtilMap.getString(saleOrderData, "ShortText1760507577966"));//交货地点
        String FNote = UtilMap.getString(saleOrderData,"LongText1758339516625");//备注
        String F_Sl_customerbillno = UtilMap.getString(saleOrderData,"ShortText1758340044946");//客户订单号

        saleOrderModel.setFBillTypeID(FBillTypeID);
        saleOrderModel.setFDate(FDate);
        saleOrderModel.setFCustId(FCustId);
        saleOrderModel.setF_NLD_DDTYPE(F_NLD_DDTYPE);
        saleOrderModel.setFSalerId(FSalerId);
        saleOrderModel.setF_Sl_gendanyuan(F_Sl_gendanyuan);
        saleOrderModel.setFBusinessType(FBusinessType);
        saleOrderModel.setF_WGR_Combo_re5(F_WGR_Combo_re5);
        saleOrderModel.setFHEADLOCID(FHEADLOCID);
        saleOrderModel.setFNote(FNote);
        saleOrderModel.setF_Sl_customerbillno(F_Sl_customerbillno);

        //财务信息
        SaleOrderFinance saleOrderFinance = new SaleOrderFinance();
        FNumber FSettleCurrId = new FNumber(UtilMap.getString(saleOrderData, "Dropdown1758339227503_key"));//结算币别
        FNumber FRecConditionId = new FNumber(UtilMap.getString(saleOrderData, "Dropdown1758339314401_key"));//收款条件
        FNumber FSettleModeId = new FNumber(UtilMap.getString(saleOrderData, "Dropdown1758340854092_key"));//结算方式
        boolean FIsIncludedTax = UtilMap.getBoolean(saleOrderData,"Logic1758340099868");//是否含税
        boolean FIsPriceExcludeTax = UtilMap.getBoolean(saleOrderData,"Logic1758340955492");//价外税

        saleOrderFinance.setFSettleCurrId(FSettleCurrId);
        saleOrderFinance.setFRecConditionId(FRecConditionId);
        saleOrderFinance.setFSettleModeId(FSettleModeId);
        saleOrderFinance.setFIsIncludedTax(FIsIncludedTax);
        saleOrderFinance.setFIsPriceExcludeTax(FIsPriceExcludeTax);

        saleOrderModel.setFSaleOrderFinance(saleOrderFinance);

        //明细信息
        List<Map> saleDetailList = UtilMap.getList(saleOrderData, "Sheet1758341252878");
        List<SaleOrderEntry> saleOrderEntryList = new ArrayList<>();


        for (Map saleDetail : saleDetailList) {
            FNumber FMaterialId = new FNumber(UtilMap.getString(saleDetail, "ShortText1758341332222"));//物料编码
            FNumber FUnitID = new FNumber(UtilMap.getString(saleDetail, "Text1758341368975"));//销售单位
            Double FQty = UtilMap.getDouble(saleDetail, "Number1758341381523");//销售数量
            FNumber FPriceUnitId = new FNumber(UtilMap.getString(saleDetail, "Text1763091074956"));//计价单位
            Double FPriceUnitQty = UtilMap.getDouble(saleDetail, "Number1763091134020");//计价数量

            String F_Sl_XSTYPE = UtilMap.getString(saleDetail, "Dropdown1758341293022_key");//产品类别

            Double FTaxPrice = UtilMap.getDouble(saleDetail, "Number1758341424993");//含税单价
            boolean FIsFree = UtilMap.getBoolean(saleDetail,"Logic1758341430353");//是否赠品
            Double FEntryTaxRate = UtilMap.getDouble(saleDetail, "Number1758349078527");//税率
            String FDeliveryDate = UtilMap.getString(saleDetail,"Date1758341499356");//客户交期
            String FEntryNote = UtilMap.getString(saleDetail,"Date1758341499356");//备注
            Double F_VMKV_MPPRICE = UtilMap.getDouble(saleDetail, "Number1758341576099");//报价价格
            String F_VMKV_SCCQ1 = UtilMap.getString(saleDetail,"Dropdown1760425152219_key");//生产厂区
            String F_VMKV_JSYQ = UtilMap.getString(saleDetail,"ShortText1762135907570");//技术要求
            String F_NLD_BR = UtilMap.getString(saleDetail,"ShortText1762135907570");//剩磁（Br）
            String F_NLD_Hcj = UtilMap.getString(saleDetail,"ShortText1762135907570");//内禀矫顽力（Hcj）
            String F_NLD_Hcb = UtilMap.getString(saleDetail,"ShortText1762135907570");//磁感矫顽力（Hcb）
            String F_NLD_BH = UtilMap.getString(saleDetail,"ShortText1762135907570");//最大磁能积（BH）max
            String F_NLD_Hk = UtilMap.getString(saleDetail,"ShortText1762135907570");//方形度Hk/Hcj
            String F_VMKV_GXYQ = UtilMap.getString(saleDetail,"ShortText1762135907570");//公差要求

            boolean FDeliveryControl = UtilMap.getBoolean(saleDetail,"Logic1763091193161");//控制发货数量
            Double FDeliveryMaxQty = UtilMap.getDouble(saleDetail, "Number1763091294543");//发货上限
            Double FDeliveryMinQty = UtilMap.getDouble(saleDetail, "Number1763091312359");//发货下限

            String cpzldj = UtilMap.getString(saleDetail, "Dropdown1763691625033");//产品质量等级
            String khwlbm = UtilMap.getString(saleDetail, "ShortText1763691936661");//客户物料编码
            FNumber khxn = new FNumber(UtilMap.getString(saleDetail, "ShortText1763691937321"));//客户性能

            SaleOrderEntry saleOrderEntry = new SaleOrderEntry();
            saleOrderEntry.setFMaterialId(FMaterialId);
            saleOrderEntry.setFUnitID(FUnitID);
            saleOrderEntry.setFPriceUnitId(FPriceUnitId);
            saleOrderEntry.setFPriceUnitQty(FPriceUnitQty);
            saleOrderEntry.setF_Sl_XSTYPE(F_Sl_XSTYPE);
            saleOrderEntry.setFQty(FQty);
            saleOrderEntry.setFTaxPrice(FTaxPrice);
            saleOrderEntry.setFIsFree(FIsFree);
            saleOrderEntry.setFEntryTaxRate(FEntryTaxRate);
            saleOrderEntry.setFDeliveryDate(FDeliveryDate);
            saleOrderEntry.setFEntryNote(FEntryNote);
            saleOrderEntry.setF_VMKV_MPPRICE(F_VMKV_MPPRICE);
            saleOrderEntry.setF_VMKV_SCCQ1(F_VMKV_SCCQ1);
            saleOrderEntry.setF_VMKV_JSYQ(F_VMKV_JSYQ);
            saleOrderEntry.setF_NLD_BR(F_NLD_BR);
            saleOrderEntry.setF_NLD_Hcj(F_NLD_Hcj);
            saleOrderEntry.setF_NLD_Hcb(F_NLD_Hcb);
            saleOrderEntry.setF_NLD_BH(F_NLD_BH);
            saleOrderEntry.setF_NLD_Hk(F_NLD_Hk);
            saleOrderEntry.setF_VMKV_GXYQ(F_VMKV_GXYQ);
            saleOrderEntry.setFDeliveryControl(FDeliveryControl);
            saleOrderEntry.setFDeliveryMaxQty(FDeliveryMaxQty);
            saleOrderEntry.setFDeliveryMinQty(FDeliveryMinQty);
            saleOrderEntry.setF_WGR_Combo_qtr(cpzldj);
            saleOrderEntry.setF_NLD_khwl(khwlbm);
            saleOrderEntry.setF_Sl_salexingnengid(khxn);

            //todo 订单图纸附件上传
            List<Map> attachments = UtilMap.getList(saleDetail, "Attachment1763102109764");
            if (!attachments.isEmpty()){
                Map attachment = attachments.get(0);
                String refId = UtilMap.getString(attachment, "refId");
                String fileName = UtilMap.getString(attachment, "name");

                String escapeRefId = new String(Base64.getUrlDecoder().decode(refId), StandardCharsets.UTF_8).substring(5);

                String filePath = "/home/data/cloudpivot/file/"+escapeRefId.substring(0,2)+"/"+escapeRefId.substring(2,4)+"/"+escapeRefId;

//                String fileName2 = "4.png";
//                String filePath2 = "C:\\Users\\EDY\\Pictures\\4.png";

                String fileId = kdUpload(fileName, filePath);

                saleOrderEntry.setF_Sl_Attachment(fileId);
            }

            saleOrderEntryList.add(saleOrderEntry);
        }

        saleOrderModel.setFSaleOrderEntry(saleOrderEntryList);

        save.setModel(saleOrderModel);
        Gson gson2 = new Gson();
        String jsonData = gson2.toJson(save);

        log.info(jsonData);

        K3CloudApi client = new K3CloudApi(initIden());
        //业务对象标识
        String formId = "SAL_SaleOrder";
        //调用接口
        String resultJson = "";
        try {
            resultJson = client.save(formId,jsonData);
        }catch (Exception e){
            throw new RuntimeException(e);
        }
        //用于记录结果
        Gson gson = new Gson();
        //对返回结果进行解析和校验
        RepoRet repoRet = gson.fromJson(resultJson, RepoRet.class);

        String saleOrderCode = "";

        if (isTrue(repoRet)){
            String id = repoRet.getResult().getId();
            Submit submit = new Submit();
            submit.setIds(id);
            //提交客户
            String resultJson2 = "";
            try {
                resultJson2 = client.submit(formId, JSONObject.toJSONString(submit));
            }catch (Exception e){
                throw new RuntimeException(e);
            }
            RepoRet repoRet2 = gson.fromJson(resultJson2, RepoRet.class);
            isTrue(repoRet2);
            saleOrderCode = repoRet2.getResult().getResponseStatus().getSuccessEntitys().get(0).getNumber();
            //回写云枢销售订单编号
            cpClient.updateCpBo("XSDD",UtilMap.map("id, ShortText1758339123133",objectId,saleOrderCode),null);

            if (isTrue(repoRet2)){
                Audit audit = new Audit();
                audit.setNumbers(Arrays.asList(saleOrderCode));
                //审核销售订单
                String resultJson3 = "";
                try {
                    resultJson3 = client.audit(formId,JSONObject.toJSONString(audit));
                }catch (Exception e){
                    throw new RuntimeException(e);
                }

                RepoRet repoRet3 = gson.fromJson(resultJson3, RepoRet.class);
                isTrue(repoRet3);
            }
        }


        return McR.success(saleOrderCode);
    }

    @Async
    @Override
    public McR createTbProject(Map map) {
        //查询云枢重要样品打样申请详情
        String objectId = UtilMap.getString(map, "objectId");

        Map proofing = cpClient.getCpBo("ZYYPDYSQ", objectId, null);

        Map proofingData = cpClient.getCpBoResultData(proofing);

        String projectName = UtilMap.getString(proofingData, "ShortText1758525084919");
        String templateId = UtilMap.getString(proofingData, "Dropdown1760517115491_key");

        Map body = new HashMap();
        body.put("name",projectName);
        body.put("templateId",templateId);

        TBR tbr = (TBR) UtilHttp.doPost("https://open.teambition.com/api/v3/project/create-from-template", initTbHeaderToken(), null,body, TBR.class);
        Map result = (Map) tbr.getResult();
        String id = result.get("id").toString();

        //更新云枢打样申请项目id
        cpClient.updateCpBo("ZYYPDYSQ",UtilMap.map("id, ShortText1760517617788",objectId,id),null);

        return McR.success(id);
    }

    @Override
    public McR getCustomerDzmx(String startDate, String endDate, String customerName) {
        List<Map> customerDzmx = jinlunMapper.getCustomerDzmx(startDate, endDate, customerName);

        return McR.success(customerDzmx);
    }

    @Override
    public McR getCustomerWqqk(String startDate, String customerName) {
        Map customerWqqk = jinlunMapper.getCustomerWqqk(startDate, customerName);

        return McR.success(customerWqqk);
    }

    @Override
    public McR queryFromData(Map map) {
        if (PublicUtil.isNull(map, "schemaCode","propertyCode","propertyValue")){
            return McR.error("201","参数不能为空！");
        }
        Map cpBoList=cpClient.getCpBoList(UtilMap.getString(map,"schemaCode"), UtilMap.map("queryFilterType, propertyCode, propertyValue", "Eq", UtilMap.getString(map,"propertyCode"), UtilMap.getString(map,"propertyValue")), null, 0, 1, null);
        Map bizObjectPage = UtilMap.getMap(UtilMap.getMap(cpBoList, "data"),"bizObjectPage");
        int totalElements = UtilMap.getInt(bizObjectPage, "totalElements");
        if (totalElements == 1){
            Map content = ((List<Map>) UtilMap.getList(bizObjectPage, "content")).get(0);
            Map data = UtilMap.getMap(content, "data");
            return McR.success(data);
        }
        return McR.error("201","未查询到数据！");
    }

    private IdentifyInfo initIden(){
        //注意 1：此处不再使用参数形式传入用户名及密码等敏感信息，改为在登录配置文件中设置。
        //注意 2：必须先配置第三方系统登录授权信息后，再进行业务操作，详情参考各语言版本SDK介绍中的登录配置文件说明。
        //读取配置，初始化SDK
        IdentifyInfo iden = new IdentifyInfo();
        iden.setUserName(kdWebApiConf.getXKDApiUserName());
        iden.setAppId(kdWebApiConf.getXKDApiAppID());
        iden.setdCID(kdWebApiConf.getXKDApiAcctID());
        iden.setAppSecret(kdWebApiConf.getXKDApiAppSec());
        iden.setServerUrl(kdWebApiConf.getXKDApiServerUrl());

        return iden;
    }


    private boolean isTrue(RepoRet repoRet){
        Gson gson = new Gson();

        if (repoRet.getResult().getResponseStatus().isIsSuccess()) {
            System.out.printf("接口返回结果: %s%n", gson.toJson(repoRet.getResult()));
            return true;
        } else {
            fail("接口返回结果: " + gson.toJson(repoRet.getResult().getResponseStatus()));
            return false;
        }
    }

    private Map<String, String> initTbHeaderToken() {
        Map header = new HashMap();
        header.put("Authorization", getTbAccessToken());
        header.put("X-Tenant-Id", tbConf.getTenantId());
        header.put("X-Tenant-Type", "organization");
        header.put("x-operator-id", tbConf.getOperatorId());
        return header;
    }

    private String getTbAccessToken() {
        synchronized(this.$lock) {
            String accessToken = UtilToken.get("invalid-token-teambition");
            if (StringUtils.isNotBlank(accessToken)) {
                return accessToken;
            } else {
                Algorithm algorithm = Algorithm.HMAC256(tbConf.getAppSecret());
                long timestamp = System.currentTimeMillis();
                Date issuedAt = new Date(timestamp);
                Date expiresAt = new Date(timestamp + EXPIRES_IN);
                accessToken = JWT.create().withClaim("_appId", tbConf.getAppID()).withIssuedAt(issuedAt).withExpiresAt(expiresAt).sign(algorithm);
                log.info("响应token, {}", accessToken);
                UtilToken.put("invalid-token-teambition", accessToken, EXPIRES_IN);
                return accessToken;
            }
        }
    }

    private String kdUpload(String fileName,String filePath){
        try {
            // 1. 读取文件为字节数组
            byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));

            // 2. 转换为Base64字符串
            String base64String = "";

            K3CloudApi client = new K3CloudApi(initIden());

            // 定义分块大小（4MB）
            final int CHUNK_SIZE = 4 * 1024 * 1024;

            long fileSize = fileBytes.length;

            String fileId = null;

            //sdk无直接上传附件接口 临时将附件上传并绑定固定单据 得到fileId
            Map map = new HashMap();
            map.put("FileName", fileName);//文件名
            map.put("FormId", "SAL_SaleOrder");//表单id
            map.put("InterId", "104784");//单据内码
            map.put("BillNO", "S301-251118005");//单据编号


            // 如果文件小于等于4MB，直接上传
            if (fileSize <= CHUNK_SIZE) {
                base64String = Base64.getEncoder().encodeToString(fileBytes);

                map.put("IsLast", true);//是否最后一次上传
                map.put("SendByte", base64String);//文件字节数组转base64后的字符串

                String resultJson = client.attachmentUpload(JSONObject.toJSONString(map));

                Map parse = (Map) JSONObject.parse(resultJson);

                Map map1 = UtilMap.getMap(parse, "Result");

                fileId = UtilMap.getString(map1, "FileId");

                return fileId;
            }

            // 分块上传逻辑
            int totalChunks = (int) Math.ceil((double) fileSize / CHUNK_SIZE);

            for (int i = 0; i < totalChunks; i++) {
                // 计算当前块的起始和结束位置
                int start = i * CHUNK_SIZE;
                int end = (int) Math.min(start + CHUNK_SIZE, fileSize);
                int chunkLength = end - start;

                // 提取当前分块的数据
                byte[] chunkBytes = new byte[chunkLength];
                System.arraycopy(fileBytes, start, chunkBytes, 0, chunkLength);

                // 转换为Base64字符串
                base64String = Base64.getEncoder().encodeToString(chunkBytes);

                // 第一个块需要获取FileId，后续块需要携带FileId
                boolean isLastChunk = (i == totalChunks - 1);

                if (i == 0) {
                    // 第一个块，IsLast为false
                    map.put("IsLast", false);
                    map.put("SendByte", base64String);//文件字节数组转base64后的字符串

                    String resultJson = client.attachmentUpload(JSONObject.toJSONString(map));

                    Map parse = (Map) JSONObject.parse(resultJson);

                    Map map1 = UtilMap.getMap(parse, "Result");

                    fileId = UtilMap.getString(map1, "FileId");
                } else {
                    // 后续块，需要携带FileId
                    map.put("FileId", fileId);
                    map.put("IsLast", isLastChunk);
                    map.put("SendByte", base64String);//文件字节数组转base64后的字符串

                    String resultJson = client.attachmentUpload(JSONObject.toJSONString(map));
                }
            }

            System.out.println(fileId);

            return fileId;
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /*private String kdUpload(String fileName, String filePath) {
        try {
            // 定义分块大小（4MB）
            final int CHUNK_SIZE = 4 * 1024 * 1024;

            // 1. 读取文件为字节数组
            byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
            long fileSize = fileBytes.length;

            String fileId = null;

            // 如果文件小于等于4MB，直接上传
            if (fileSize <= CHUNK_SIZE) {
                String base64String = Base64.getEncoder().encodeToString(fileBytes);

                Map<String, Object> body = new HashMap<>();
                Map<String, Object> data = new HashMap<>();
                data.put("FileName", fileName);
                data.put("SendByte", base64String);
                data.put("IsLast", true);
                body.put("data",data);

                // 调用上传接口（带会话检查）
                Map<String, Object> result = uploadWithSessionCheck(body, true);

                // 获取FileId
                Map<String, Object> resultData = UtilMap.getMap(result, "Result");
                fileId = UtilMap.getString(resultData, "FileId");

                return fileId;
            }

            // 分块上传逻辑
            int totalChunks = (int) Math.ceil((double) fileSize / CHUNK_SIZE);

            for (int i = 0; i < totalChunks; i++) {
                // 计算当前块的起始和结束位置
                int start = i * CHUNK_SIZE;
                int end = (int) Math.min(start + CHUNK_SIZE, fileSize);
                int chunkLength = end - start;

                // 提取当前分块的数据
                byte[] chunkBytes = new byte[chunkLength];
                System.arraycopy(fileBytes, start, chunkBytes, 0, chunkLength);

                // 转换为Base64字符串
                String base64String = Base64.getEncoder().encodeToString(chunkBytes);

                // 准备请求体
                Map<String, Object> body = new HashMap<>();
                Map<String,Object> data = new HashMap<>();
                data.put("FileName", fileName);
                data.put("SendByte", base64String);
                body.put("data",data);

                // 第一个块需要获取FileId，后续块需要携带FileId
                boolean isLastChunk = (i == totalChunks - 1);

                if (i == 0) {
                    // 第一个块，IsLast为false
                    body.put("IsLast", false);

                    // 调用上传接口（带会话检查）
                    Map<String, Object> result = uploadWithSessionCheck(body, false);

                    // 获取FileId
                    Map<String, Object> resultData = UtilMap.getMap(result, "Result");
                    fileId = UtilMap.getString(resultData, "FileId");
                } else {
                    // 后续块，需要携带FileId
                    body.put("FileId", fileId);
                    body.put("IsLast", isLastChunk);

                    // 调用上传接口（带会话检查）
                    uploadWithSessionCheck(body, isLastChunk);
                }
            }

            return fileId;
        } catch (Exception e) {
            throw new RuntimeException("文件上传失败: " + e.getMessage(), e);
        }
    }

    // 带会话检查的上传方法（支持单块和多块上传）
    private Map<String, Object> uploadWithSessionCheck(Map<String, Object> body, boolean isLastChunk) {
        while (true) {
            try {
                // 调用上传接口
                Map<String, Object> result = (Map<String, Object>) JSONObject.parse(UtilHttp.doPost(kdWebApiConf.getXKDApiServerUrl() + "Kingdee.BOS.WebApi.ServicesStub.DynamicFormService.UploadFile.common.kdsvc", null, null, body));

                // 检查响应状态
                checkResponseStatus(result);

                return result;
            } catch (RuntimeException e) {
                // 解析错误响应
                try {
                    Map<String, Object> responseStatus = (Map<String, Object>) JSONObject.parse(e.getMessage());

                    // 如果是会话丢失错误
                    if (responseStatus != null && UtilMap.getString(((List<Map>)UtilMap.getList(responseStatus, "Errors")).get(0),"Message").equals("会话信息已丢失，请重新登录")) {
                        // 重新登录
                        kdLogin();

                        // 如果是最后一块上传失败，需要设置IsLast为true
                        if (isLastChunk) {
                            body.put("IsLast", true);
                        }

                        // 重试上传
                        continue;
                    }
                } catch (Exception parseException) {
                    // 如果不是会话丢失错误，直接抛出原始异常
                    throw e;
                }

                // 如果不是会话丢失错误，直接抛出原始异常
                throw e;
            }
        }
    }

    // 检查响应状态
    private void checkResponseStatus(Map<String, Object> result) {
        if (result == null || !result.containsKey("Result")) {
            throw new RuntimeException("无效的响应格式");
        }

        Map<String, Object> resultData = UtilMap.getMap(result, "Result");
        Map<String, Object> responseStatus = UtilMap.getMap(resultData, "ResponseStatus");

        if (responseStatus == null || !UtilMap.getBoolean(responseStatus, "IsSuccess")) {
            String message = UtilMap.getString(resultData, "Message");
            // 如果有错误码，也包含在异常信息中
            int errorCode = UtilMap.getInt(responseStatus, "ErrorCode");
            if (errorCode != 0) {
                message = "错误码: " + errorCode + ", 消息: " + message;
                log.info("message: {}", message);
            }
            throw new RuntimeException(JSONObject.toJSONString(responseStatus));
        }
    }
    private void kdLogin(){
        try {
            //金蝶登录
            String acctID = kdWebApiConf.getXKDApiAcctID();
            String username = kdWebApiConf.getXKDApiUserName();
            String appId = kdWebApiConf.getXKDApiAppID();
            String appSec = kdWebApiConf.getXKDApiAppSec();
            String timestamp = System.currentTimeMillis()/1000 + "";

            String[] arr = {acctID,username,appId,appSec,timestamp};

            Arrays.sort(arr, String::compareTo);

            String str = String.join("", arr);

            // 1. 创建 MessageDigest 实例，指定 SHA-256 算法
            MessageDigest digest = MessageDigest.getInstance("SHA-256");

            // 2. 输入字符串转换为字节数组，并计算哈希值
            byte[] hashBytes = digest.digest(str.getBytes(StandardCharsets.UTF_8));

            // 3. 将字节数组转换为十六进制字符串
            StringBuilder sign = new StringBuilder();
            for (byte b : hashBytes) {
                String hex = Integer.toHexString(0xff & b);
                if (hex.length() == 1) {
                    sign.append('0'); // 补零
                }
                sign.append(hex);
            }

            // 4. 输出结果
            System.out.println("SHA-256 哈希值: " + sign.toString());

            Map body = new HashMap();
            body.put("acctID",acctID);
            body.put("username",username);
            body.put("appId",appId);
            body.put("timestamp",timestamp);
            body.put("sign",sign.toString());
            body.put("lcid",2052);

            UtilHttp.doPost(kdWebApiConf.getXKDApiServerUrl() + "Kingdee.BOS.WebApi.ServicesStub.AuthService.LoginBySign.common.kdsvc", null, null, body);

        }catch (Exception e){
            throw new RuntimeException(e);
        }

    }*/

}
