package org.dromara.payment.thirdPlatform.xinyujian.service;

import cn.hutool.core.lang.UUID;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.esotericsoftware.kryo.kryo5.minlog.Log;
import com.google.gson.Gson;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.RandomStringUtils;
import org.dromara.common.core.service.BaseService;
import org.dromara.payment.bill.domain.MerBill;
import org.dromara.payment.bill.domain.MerBillDetail;
import org.dromara.payment.bill.mapper.MerBillDetailMapper;
import org.dromara.payment.invoice.domain.MerInvoice;
import org.dromara.payment.invoice.domain.MerInvoiceDetail;
import org.dromara.payment.invoice.mapper.MerInvoiceDetailMapper;
import org.dromara.payment.invoice.mapper.MerInvoiceMapper;
import org.dromara.payment.merchant.domain.BusMerchant;
import org.dromara.payment.merchant.domain.BusMerchantAccount;
import org.dromara.payment.merchant.mapper.BusMerchantMapper;
import org.dromara.payment.merchant.service.IBusMerchantAccountService;
import org.dromara.payment.sys.domain.SysSyd;
import org.dromara.payment.sys.domain.bo.SysSydBo;
import org.dromara.payment.sys.domain.vo.SysSydVo;
import org.dromara.payment.sys.mapper.SysSydMapper;
import org.dromara.payment.sys.service.ISysSydService;
import org.dromara.payment.task.domain.MerTask;
import org.dromara.payment.task.mapper.MerTaskMapper;
import org.dromara.payment.taxRecords.domain.MerTaxRecords;
import org.dromara.payment.taxRecords.domain.vo.MerTaxRecordsVo;
import org.dromara.payment.taxRecords.mapper.MerTaxRecordsMapper;
import org.dromara.payment.thirdPlatform.base.domain.SysThirdPlatform;
import org.dromara.payment.thirdPlatform.base.mapper.SysThirdPlatformMapper;
import org.dromara.payment.thirdPlatform.xinyujian.config.XyjConfig;
import org.dromara.payment.thirdPlatform.xinyujian.domain.ThirdItemTaskTypes;
import org.dromara.payment.thirdPlatform.xinyujian.domain.bo.ThirdItemTaskTypesBo;
import org.dromara.payment.thirdPlatform.xinyujian.domain.vo.ThirdItemTaskTypesVo;
import org.dromara.payment.thirdPlatform.xinyujian.mapper.ThirdItemTaskTypesMapper;
import org.dromara.payment.thirdPlatform.xinyujian.sign.BaseDataVo;
import org.dromara.payment.thirdPlatform.xinyujian.sign.MyRSA;
import org.dromara.payment.worker.domain.UserWorker;
import org.dromara.payment.worker.domain.UserWorkerBusiness;
import org.dromara.payment.worker.domain.vo.UserWorkerVo;
import org.dromara.payment.worker.mapper.UserWorkerBusinessMapper;
import org.dromara.payment.worker.mapper.UserWorkerMapper;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author sunzexing
 * @version 1.0
 * @title XyjServerImpl
 * @description
 * @create 2025-03-28 14:27
 */

@Slf4j
@Data
@Service
public class XyjServerImpl extends BaseService implements IXyjService {

    @Resource
    public SysThirdPlatformMapper sysThirdPlatformMapper;

    @Resource
    public ThirdItemTaskTypesMapper thirdItemTaskTypesMapper;

    @Resource
    public UserWorkerBusinessMapper userWorkerBusinessMapper;

    @Resource
    public MerBillDetailMapper  merBillDetailMapper;

    @Resource
    public MerInvoiceDetailMapper merInvoiceDetailMapper;

    @Resource
    public SysSydMapper sysSydMapper;

    @Resource
    public MerInvoiceMapper merInvoiceMapper;

    @Resource
    public UserWorkerMapper userWorkerMapper;

    @Resource
    public MerTaskMapper merTaskMapper;

    @Resource
    public BusMerchantMapper busMerchantMapper;

    @Resource
    public ISysSydService sysSydService;

    @Resource
    public IBusMerchantAccountService busMerchantAccountService;

    @Resource
    public IThirdItemTaskTypesService thirdItemTaskTypesService;;

    @Resource
    public MerTaxRecordsMapper merTaxRecordsMapper;

    @Override
    public boolean addMerchant(BusMerchant busMerchant,Long sydId) {
        XyjConfig config = this.getXyjAppInfo(sydId);
        JSONObject data = new JSONObject();
        //企业名称
        data.put("companyName", busMerchant.getName());
        //企业社会统一信用代码
        data.put("creditCode", busMerchant.getNsrSbh());
        //企业地址
        data.put("companyAddr", busMerchant.getAddress());
        //企业电话
        data.put("companyMobile", busMerchant.getFrSjh());
        //灵活用工场景编码
        data.put("serviceTypeId", busMerchant.getIndustryCode());


        //注册资本（单位：万
        //元）
        data.put("registeredAssets", busMerchant.getRegisteredAssets());

        Date date = busMerchant.getRegdate();  // 或从其他来源获取Date对象
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String formattedDate = sdf.format(date);


        //注册时间
        data.put("regdate", formattedDate);



        //企业开户行
        data.put("bankName", busMerchant.getKhh());
        //企业银行账户
        data.put("bankAcct", busMerchant.getBankCard());
        //企业联系人
        data.put("contactName", busMerchant.getWtr());
        //企业联系人手机号
        data.put("contactMobile", busMerchant.getWtrSjh());
        //法人姓名
        data.put("legalPersonName", busMerchant.getFr());
        //法人身份证号
        data.put("idNo", busMerchant.getFrSfz());
        //营业执照照片
        data.put("businessLicense", busMerchant.getYyzz());
        //基本存款账号信息表
        data.put("accountLicense", busMerchant.getName());
        //办公场地门头照
        //注册时间小于6个月必传
        data.put("houseNumberImg", busMerchant.getMtqjzPic());
        //办公场地场所照
        //注册时间小于6个月必传
        data.put("officeSpaceImg", busMerchant.getBgzp1Pic());
        //办公场地前台照
        //注册时间小于6个月必传
        data.put("receptionImg", busMerchant.getBgzp2Pic());
        //入驻回调通知URL
        data.put("callBackUrl", busMerchant.getName());
        //来账通知回调地址
        data.put("bookedNoticeUrl", busMerchant.getName());
        //短信签约回调地址 用户
        //签约成功后通过该地址
        //回调
        data.put("SignChangeNoticeUrl", busMerchant.getName());
        String paramStr = JSON.toJSONString(data);
        String sendMsg = createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(), paramStr);
        log.info("企业注入新遇见平台，参数：{}", paramStr);
        log.info("企业注入新遇见平台，加密后信息：{}",sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/company/register",sendMsg);
        log.info("企业注入新遇见平台，返回信息：{}",result);
        BaseDataVo vo = decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        log.info("企业注入新遇见平台，result：{}", JSON.toJSONString(vo));


        log.info("企业注入新遇见平台，返回信息：{}", vo.getData());



        JSONObject resultJson = JSON.parseObject(vo.getData().toString());
        if(resultJson != null){
            String status = resultJson.getString("status");
            String businessId = resultJson.getString("businessId");
            BusMerchant busMerchant1 = new BusMerchant();
            busMerchant1.setBusinessId(businessId);
            busMerchant1.setId(busMerchant.getId());
            busMerchant1.setBusinessStatus(status);
            this.busMerchantMapper.updateById(busMerchant1);
            if("11".equals(status)){
                this. addMerchantResultSel(businessId, sydId);
            }
        }

        return true;
    }


    @Override
    public boolean createProjectTask(MerTask task,BusMerchant merchant) {
        XyjConfig config = this.getXyjAppInfo(task.getSydId());
        this.queryPark(merchant.getBusinessId(), task.getSydId());
        SysSyd sysSyd = sysSydMapper.selectSysSydById(task.getSydId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessId",merchant.getBusinessId());
        jsonObject.put("parkId",sysSyd.getParkId());
        jsonObject.put("commissionType","04");
        jsonObject.put("commissionLow",task.getCost());
        jsonObject.put("commissionHigh",task.getCostMax());
        jsonObject.put("itemPeriod","04");
        jsonObject.put("checkRequire","01");
        jsonObject.put("checkPeriod","1");
        List<JSONObject> taskObjectList = new ArrayList<>();

        ThirdItemTaskTypes thirdItemTaskTypes =
            thirdItemTaskTypesMapper.selectOne(new QueryWrapper<ThirdItemTaskTypes>().eq("business_id", merchant.getBusinessId()).eq("park_id", sysSyd.getParkId()));
        jsonObject.put("itemTitle",task.getName());
        jsonObject.put("itemTypeId",thirdItemTaskTypes.getItemType());
        JSONObject taskObject = new JSONObject();
        taskObject.put("taskTitle",task.getName());
        taskObject.put("taskTypeId",thirdItemTaskTypes.getTaskType());
        taskObject.put("commissionType","01");
        taskObject.put("commissionLow",task.getCost());
        taskObject.put("commissionHigh",task.getCostMax());
        taskObject.put("taskPeriod","04");
        taskObject.put("checkRequire","01");
        taskObject.put("checkPeriod","1");
        taskObject.put("recruitType","2");
        taskObject.put("deliveryType","2");
        taskObjectList.add(taskObject);
        jsonObject.put("taskInfo",taskObjectList);
        log.info("企业注入新遇见平台创建项目和任务，参数：{}", jsonObject.toString());
        String sendMsg = createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(),JSON.toJSONString(jsonObject));
        log.info("企业注入新遇见平台创建项目和任务，加密后信息：{}",sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/item/create",sendMsg);
        BaseDataVo vo = decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        log.info("企业注入新遇见平台创建项目和任务，result：{}", JSON.toJSONString(vo));

        if(!this.checkSuccess(vo)){
            throw new RuntimeException("创建项目失败");
        }

        JSONObject resultJson = JSON.parseObject(vo.getData().toString());
        if(resultJson != null){
            String itemId = resultJson.getString("itemId");
            JSONArray taskInfo = resultJson.getJSONArray("taskInfo");
            if(taskInfo != null){
              String taskId =  ((JSONObject)taskInfo.get(0)).getString("taskId");
              MerTask merTask = new MerTask();
              merTask.setId(task.getId());
              merTask.setTaskId(taskId);
              merTask.setItemId(itemId);
              this.merTaskMapper.updateById(merTask);
            }else{
                throw new RuntimeException("创建任务失败");
            }
        }
        return true;
    }

    @Override
    public boolean createTask(MerTask task,BusMerchant merchant) {
        return false;
    }

    @Override
    public boolean recruitBatch(MerBill bill, List<MerBillDetail> detailList, BusMerchant merchant, SysSyd syd,
                                MerTask task) {
        XyjConfig config = this.getXyjAppInfo(syd.getId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessId",merchant.getBusinessId());
        jsonObject.put("taskId",task.getTaskId());
        jsonObject.put("outBatchNo",bill.getId());
        jsonObject.put("total",detailList.size());
        List<JSONObject> freelancers = new ArrayList<>();
        for(MerBillDetail detail : detailList){
            JSONObject detailObj = new JSONObject();
            detailObj.put("outSeqNo",detail.getId());
            detailObj.put("name",detail.getWorkerName());
            detailObj.put("idno",detail.getCardId());
            detailObj.put("mobile",detail.getWorkerPhone());
            freelancers.add(detailObj);
        }

        jsonObject.put("freelancers",freelancers);

        String sendMsg = createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(),JSON.toJSONString(jsonObject));
        Log.info("企业新遇见平台任务认领，加密后信息：{}",sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/recruit/recruitBatch",sendMsg);
        BaseDataVo vo = decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        return false;
    }

    @Override
    public boolean recruitOne(MerBill bill) {
        return false;
    }

    @Override
    public boolean settleBatch(MerBill bill, List<MerBillDetail> detailList, SysSyd syd, BusMerchant merchant, MerTask task,
                               BusMerchantAccount account) {

        XyjConfig config = this.getXyjAppInfo(syd.getId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessId",merchant.getBusinessId());
        jsonObject.put("taskId",task.getTaskId());
        jsonObject.put("acctNo",account.getBankVirtualCard());
        jsonObject.put("outBatchNo",bill.getId());
        jsonObject.put("totalSettleFee",bill.getMoney());
        jsonObject.put("total",detailList.size());
        List<JSONObject> freelancers = new ArrayList<>();
        detailList.forEach(item -> {
            JSONObject detailObj = new JSONObject();
            detailObj.put("outSeqNo",item.getId());
            detailObj.put("name",item.getWorkerName());
            detailObj.put("idno",item.getCardId());
            detailObj.put("acctNo",item.getBankCard());
            detailObj.put("settleFee",item.getAmount());
            freelancers.add(detailObj);
        });
        jsonObject.put("freelancers",freelancers);
        String sendMsg = createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(),JSON.toJSONString(jsonObject));
        Log.info("企业新遇见平台批量结算，加密后信息：{}",sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/recruit/settleBatch",sendMsg);
        BaseDataVo vo = decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        Log.info("企业新遇见平台批量结算，result：{}", JSON.toJSONString(vo));
        if (!this.checkSuccess(vo)){
            throw new RuntimeException("提交薪遇见结算失败");
        }
        return true;
    }

    @Override
    public boolean signFind(BusMerchant merchant, SysSyd syd, UserWorker userWorker) {

        XyjConfig config = this.getXyjAppInfo(syd.getId());

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessId", merchant.getBusinessId());
        jsonObject.put("idNo", userWorker.getCardId());
        String sendMsg = createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(),JSON.toJSONString(jsonObject));
        log.info("签约查询:{}",sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/recruit/signFind ",sendMsg);
        BaseDataVo vo = decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        if(vo.getData() != null ){
                JSONObject resultJson = (JSONObject)vo.getData();
                String sign = resultJson.getString("sign");
                String signUrl = resultJson.getString("signUrl");
                String signDownloadUrl = resultJson.getString("signDownloadUrl");
                if("1".equals(sign)){
                    //已签约
                    this.userWorkerBusinessMapper.update(new LambdaUpdateWrapper<UserWorkerBusiness>()
                        .eq(UserWorkerBusiness::getWorkId, userWorker.getId())
                        .eq(UserWorkerBusiness::getSydId, syd.getId())
                        .set(UserWorkerBusiness::getSignStatus, 1)
                        .set(UserWorkerBusiness::getSignFileUrl, signDownloadUrl)
                    );
                }else if("0".equals(sign)){
                    //未签约
                    this.userWorkerBusinessMapper.update(new LambdaUpdateWrapper<UserWorkerBusiness>()
                        .eq(UserWorkerBusiness::getWorkId, userWorker.getId())
                        .eq(UserWorkerBusiness::getSydId, syd.getId())
                        .set(UserWorkerBusiness::getSignStatus, 0)
                        .set(UserWorkerBusiness::getSignUrl, signUrl)
                    );
                }
        }
        return true;
    }

    @Override
    public boolean applyInvoice(BusMerchant busMerchant, SysSyd syd, MerInvoice invoice) {
        XyjConfig config = this.getXyjAppInfo(syd.getId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessId",busMerchant.getBusinessId());
        jsonObject.put("outOrderNo",invoice.getId());
        jsonObject.put("parkId",syd.getParkId());
        jsonObject.put("oneObjectName",invoice.getCategoryOne());
        jsonObject.put("twoObjectName",invoice.getCategoryTwo());
        jsonObject.put("invoiceTotalFee",invoice.getInvAmount());
        //增值税普通发票 1 增值税专用发票 2  增值税普通电子发票 3 增值税专用电子发票 4
        jsonObject.put("invoiceType",invoice.getType().intValue() == 1 ? 2: 1);
        jsonObject.put("invoiceAddress",busMerchant.getName());
        jsonObject.put("invoicePhone",invoice.getAddPhone());
        jsonObject.put("invoiceAcctNo",invoice.getBankCard());
        jsonObject.put("invoiceBankName",invoice.getBankAddress());
        jsonObject.put("callBackUrl","");//回调地址

        String sendMsg = createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(),JSON.toJSONString(jsonObject));
        log.info("申请发票:{}",sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/invoice/apply",sendMsg);
        BaseDataVo vo = decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        Log.info("申请发票，result：{}", JSON.toJSONString(vo));
        if(!this.checkSuccess(vo)){
            throw new RuntimeException("开票失败");
        }
        return true;
    }


    /**
     * 组装发送消息体
     * 该方法用于创建一个发送消息的请求体，包括必要的头部信息和加密签名的数据
     *
     * @param appId 应用ID，用于标识消息的发送方
     * @param otherPublicKey 对方的公钥，用于加密数据
     * @param myPrivateKey 我方的私钥，用于生成签名
     * @param data 需要发送的原始数据
     * @return 返回组装好的、经过加密和签名的消息体的JSON字符串
     */
    private String createSendMsg(String appId, String otherPublicKey, String myPrivateKey, String data) {
        // 创建一个基础数据对象，用于承载发送消息所需的所有信息
        BaseDataVo vo = new BaseDataVo();
        // 设置应用ID
        vo.setAppid(appId);
        // 生成一个20位的随机字符串作为nonceStr，用于防止重放攻击
        vo.setNonceStr(RandomStringUtils.randomAlphanumeric(20));
        // 生成一个唯一的请求消息ID
        vo.setReqMsgId(UUID.randomUUID().toString().replace("-", ""));
        // 设置签名类型为RSA
        vo.setSignType("RSA");
        // 设置当前时间戳
        vo.setTimestamp(String.valueOf(System.currentTimeMillis()));

        try {
            // 使用对方的公钥加密原始数据
            String encryptData = MyRSA.encryptByPublicKey(data, otherPublicKey);
            // 将加密后的数据设置到请求体中
            vo.setData(encryptData);
            // 使用我方的私钥对请求体进行签名
            String signData = MyRSA.sign(JSON.toJSONString(vo), myPrivateKey);
            // 将签名设置到请求体中
            vo.setSign(signData);
        } catch (Exception e) {
            // 如果加密或签名过程中发生异常，记录错误日志并抛出运行时异常
            log.error("薪遇见加密签名异常" + appId + "\n" + e.toString());
            throw new RuntimeException(e);
        }

        // 返回组装好的请求体的JSON字符串形式
        return JSON.toJSONString(vo);
    }



    /**
     * 使用公钥解密并验证数据的完整性
     * 该方法首先将输入的数据字符串解析为BaseDataVo对象，然后验证签名并解密数据
     *
     * @param publicKey 公钥，用于验证签名
     * @param privateKey 私钥，用于解密数据
     * @param data 加密的数据字符串
     * @return 解密并验证后的BaseDataVo对象
     */
    public BaseDataVo decryptAndVerify(String publicKey, String privateKey, String data) {
        // 将数据字符串解析为BaseDataVo对象
        BaseDataVo vo = (BaseDataVo) JSONObject.parseObject(data, BaseDataVo.class);
        // 获取签名数据，并移除以便验证签名
        String signData = vo.getSign();
        vo.setSign(null);
        try {
            // 验证签名是否有效
            boolean verify = MyRSA.verify(JSON.toJSONString(vo), publicKey, signData);
            vo.setVerify(Boolean.valueOf(verify));
            // 如果签名有效且数据不为空，则解密数据
            if (verify && vo.getData() != null) {
                String decrypt = MyRSA.decryptByPrivateKey(JSON.toJSONString(vo.getData()), privateKey);
                vo.setData(decrypt);
            }
        } catch (Exception e) {
            // 记录验证或解密过程中的错误
            log.error("薪遇见验签解密失败：" + e.getMessage());
            e.printStackTrace();
        }
        // 返回处理后的BaseDataVo对象
        return vo;
    }


    /**
     * 使用公钥解密并验证数据的完整性
     * 该方法首先将输入的数据字符串解析为BaseDataVo对象，然后验证签名并解密数据
     *
     * @param publicKey 公钥，用于验证签名
     * @param privateKey 私钥，用于解密数据
     * @param vo 返回数据对象
     * @return 解密并验证后的BaseDataVo对象
     */
    public BaseDataVo decryptAndVerify(String publicKey, String privateKey, BaseDataVo vo) {
        // 将数据字符串解析为BaseDataVo对象
        // 获取签名数据，并移除以便验证签名
        String signData = vo.getSign();
        vo.setSign(null);
        try {
            // 验证签名是否有效
            boolean verify = MyRSA.verify(JSON.toJSONString(vo), publicKey, signData);
            vo.setVerify(Boolean.valueOf(verify));
            // 如果签名有效且数据不为空，则解密数据
            if (verify && vo.getData() != null) {
                String decrypt = MyRSA.decryptByPrivateKey(JSON.toJSONString(vo.getData()), privateKey);
                vo.setData(decrypt);
            }
        } catch (Exception e) {
            // 记录验证或解密过程中的错误
            log.error("薪遇见验签解密失败：" + e.getMessage());
            e.printStackTrace();
        }
        // 返回处理后的BaseDataVo对象
        return vo;
    }


    /**
     * 检查操作是否成功
     * 通过检查传入的BaseDataVo对象是否为非空且其code属性是否为"200"来判断操作是否成功
     * @param vo BaseDataVo对象，包含操作结果信息
     * @return 如果操作成功，则返回true；否则返回false
     */
    public Boolean checkSuccess(BaseDataVo vo) {
        // 检查vo对象是否为非空且其code属性是否为"200"
        if(vo != null && "200".equals(vo.getCode()))
            // 如果条件满足，表示操作成功，返回true
            return Boolean.valueOf(true);
        // 如果条件不满足，表示操作未成功，返回false
        return Boolean.valueOf(false);
    }


    /**
     * 根据第三方平台ID获取XYJ应用信息
     * 此方法用于从数据库中查询特定第三方平台的应用信息，并将其解析为XyjConfig对象
     * 如果找不到对应的信息，则抛出异常
     *
     * @param sydId 税地ID，用于查询特定的应用信息
     * @return XyjConfig对象，包含解析后的应用信息
     */
    private XyjConfig  getXyjAppInfo(Long sydId){

        // 查询第三方平台应用信息
        SysThirdPlatform sysThirdPlatform = this.sysThirdPlatformMapper.selectThirdAppInfo(sydId);

        // 如果未找到对应的信息，抛出异常
        if(sysThirdPlatform == null){
            this.invalidationParamsException("未找到对应的第三方平台信息");
        }
        // 可以加上redis进行缓存
        // 将查询到的信息解析为XyjConfig对象
        XyjConfig xyjConfig = JSONObject.parseObject(sysThirdPlatform.getOtherParams(), XyjConfig.class);
        if(xyjConfig == null){
            this.invalidationParamsException("第三方平台配置信息无效");
        }
        xyjConfig.setId(sysThirdPlatform.getId());
        // 返回解析后的配置信息
        return xyjConfig;
    }


    @Override
    @Transactional
    public boolean addMerchantCallback(BaseDataVo bdvo, Long sydId) {
        log.info("企业注入新遇见平台回调，result：{}", JSON.toJSONString(bdvo));
        XyjConfig config = getXyjAppInfo(sydId);

        this.decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), bdvo);
        if(!bdvo.getVerify()){
            throw new RuntimeException("验签失败");
        }
        JSONObject  data = (JSONObject)bdvo.getData();
        if(data == null){
            throw new RuntimeException("无数据");
        }
        addMerResultDealWidth(data, config);
        return true;
    }

    @Override
    public boolean addTaskCallback(BaseDataVo bdvo, Long sydId) {
        log.info("企业任务审核新遇见平台回调，result：{}", JSON.toJSONString(bdvo));
        XyjConfig config = getXyjAppInfo(sydId);
        JSONObject data = (JSONObject)bdvo.getData();
        if (data != null){
            String taskId = data.getString("taskId");
            String status = data.getString("status");
            Integer syd_verify_status = null;
            if("04".equals(status)){
                //审核拒绝
                syd_verify_status = 2;
            }else if("03".equals(status)){
                //审核通过
                syd_verify_status = 3;
            }
            if(syd_verify_status != null){
                this.merTaskMapper.update(new LambdaUpdateWrapper<MerTask>().eq(MerTask::getId,taskId)
                    .set(MerTask::getSydVerifyStatus,syd_verify_status));
            }
        }else{
            throw new RuntimeException("无效数据");
        }
        return true;
    }

    @Override
    public boolean addSignCallback(BaseDataVo bdvo, Long sydId) {
        log.info("签约平台回调，result：{}", JSON.toJSONString(bdvo));
        JSONObject jsonObject = (JSONObject)bdvo.getData();
        if (jsonObject != null){
            String idNo = jsonObject.getString("idNo");
            String hasSign = jsonObject.getString("hasSign");//0-未签约，1-已签约，2-已解约
            String viewContractUrl = jsonObject.getString("viewContractUrl");
            String  downloadContractUrl = jsonObject.getString("downloadContractUrl");

            UserWorkerVo userWorkerVO = this.userWorkerMapper.selectVoOne(new LambdaQueryWrapper<UserWorker>().eq(UserWorker::getCardId,idNo));
            if(userWorkerVO != null){
                if("0".equals(hasSign)){
                    this.userWorkerBusinessMapper.update(new LambdaUpdateWrapper<UserWorkerBusiness>()
                        .eq(UserWorkerBusiness::getWorkId,userWorkerVO.getId())
                            .eq(UserWorkerBusiness::getSydId,sydId)
                            .set(UserWorkerBusiness::getSignStatus,0)
                            .set(UserWorkerBusiness::getSignUrl,viewContractUrl)
                        );


                }else if("1".equals(hasSign)){
                    this.userWorkerBusinessMapper.update(new LambdaUpdateWrapper<UserWorkerBusiness>()
                        .eq(UserWorkerBusiness::getWorkId,userWorkerVO.getId())
                        .eq(UserWorkerBusiness::getSydId,sydId)
                        .set(UserWorkerBusiness::getSignStatus,1)
                        .set(UserWorkerBusiness::getSignFileUrl,downloadContractUrl)
                    );
                }
            }
        }
        return true;
    }

    /****
     * 入驻结果处理
     * @param data
     * @param config
     */
    private void addMerResultDealWidth(JSONObject data, XyjConfig config) {
        //企业ID
        String businessId = data.getString("businessId");
        String companyName = data.getString("companyName");
        //审核状态
        //00-暂存，01-提交风控审核，02-风控拒绝，待
        //运营审核，03-无效（关闭），
        //04-提交运营审核，05-运营审核拒绝，10-待配
        //置参数，11-准入成功
        String status = data.getString("status");

        this.busMerchantMapper.update(new LambdaUpdateWrapper<BusMerchant>().eq(BusMerchant::getBusinessId,businessId)
            .set(BusMerchant::getBusinessStatus,status));

        if("11".equals(status)){
            //准入成功
            JSONArray acctInfo = data.getJSONArray("acctInfo");
            if(acctInfo != null){
                SysSydBo  sysSydBo = new SysSydBo();
                sysSydBo.setThreeId(config.getId());
                List<SysSydVo> sydList = this.sysSydService.queryList(sysSydBo);
                acctInfo.forEach(item->{
                    JSONObject  acct = (JSONObject)item;
                    String acctNo = acct.getString("acctNo");//银行卡号
                    String acctName = acct.getString("acctName");//账户名
                    String parkName = acct.getString("parkName");//税源地名称
                    Long parkId = acct.getLong("parkId");//税源地 Id
                    Long limitAmount = acct.getLong("limitAmount");//单笔最大限额（整数，单位：分）
                    String bankName = acct.getString("bankName");//银行名称
                    String zfCode = acct.getString("zfCode");//支付通道编码
                    sydList.forEach(syd->{
                            if(syd.getGsmc().equals(parkName)){
                                if(syd.getParkId() == null){
                                    //绑定税源地
                                    SysSydBo  sydBo  = new SysSydBo();
                                    sydBo.setId(syd.getId());
                                    sydBo.setParkId(parkId);
                                    this.sysSydService.updateByBo(sydBo);
                                    //添加税源地企业银行账号
                                }
                                this.busMerchantAccountService.createThirdXnAccount(syd.getId(),Long.valueOf(businessId),companyName,bankName,acctNo,acctName);
                            }
                    });
                });
            }
        }
    }


    /***********
     * 根据企业id，同步企业任务类型
     * @param businessId
     * @return
     */
    @Override
    public boolean synQueryTaskTypes(String businessId, Long sydId) {
        XyjConfig config = getXyjAppInfo(sydId);
        JSONObject data = new JSONObject();
        //企业名称
        data.put("businessId", businessId);
        log.info("同步企业[{}]任务类型:", businessId);
        String sendMsg = this.createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(), data.toJSONString());
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/baseInfo/queryTaskTypes",sendMsg);
        BaseDataVo  bdvo  = this.decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        log.info("同步企业[{}]任务类型:{}", businessId, JSON.toJSONString(bdvo));

        return true;
    }

    @Override
    public boolean addMerchantResultSel(String businessId, Long sydId) {
        XyjConfig config = getXyjAppInfo(sydId);
        JSONObject data = new JSONObject();
        //企业名称
        data.put("businessId", businessId);
        log.info("查询企业[{}]入驻结果:", businessId);
        String sendMsg = this.createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(), data.toJSONString());
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/company/queryCompanyInfo",sendMsg);
        BaseDataVo  bdvo  = this.decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        log.info("查询企业[{}]入驻结果:{}", businessId, JSON.toJSONString(bdvo));
        this.addMerResultDealWidth((JSONObject)bdvo.getData(), config);
        return true;
    }

    @Override
    public boolean queryPark(String businessId, Long sydId) {

        XyjConfig config = getXyjAppInfo(sydId);
        JSONObject data = new JSONObject();
        //企业名称
        data.put("businessId", businessId);
        log.info("查询企业[{}]的税源地信息:", businessId);
        String sendMsg = this.createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(), data.toJSONString());
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/baseInfo/queryParks",sendMsg);
        BaseDataVo  bdvo  = this.decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        log.info("查询企业[{}]的税源地信息结果:{}", businessId, JSON.toJSONString(bdvo));
        String jsonString = JSON.toJSONString(bdvo);
        JSONObject Obj = JSON.parseObject(jsonString);
        String dataStr = Obj.getString("data");
        JSONArray dataArray = JSON.parseArray(dataStr);
        if(dataArray != null){
            for(int i=0;i<dataArray.size();i++){
                JSONObject dataObj = dataArray.getJSONObject(i);
                String parkId = dataObj.getString("parkId");//税源地 Id
                SysSyd  sysSyd = new SysSyd();
                sysSyd.setId(sydId);
                sysSyd.setParkId(Long.valueOf(parkId));
                sysSydMapper.insertOrUpdate(sysSyd);

                ThirdItemTaskTypesBo  itemTaskTypesBo = new ThirdItemTaskTypesBo();
                itemTaskTypesBo.setParkId(Long.valueOf(parkId));
                List<ThirdItemTaskTypesVo> itemTaskList = this.thirdItemTaskTypesService.queryList(itemTaskTypesBo);
                if(!itemTaskList.isEmpty()){
                    return true;
                }
                String parkName = dataObj.getString("parkName");//税源地名称
                JSONArray itemType = dataObj.getJSONArray("itemType");//项目类型
                List<ThirdItemTaskTypes> itemTaskTypess = new ArrayList<>();
                if(itemType != null){
                    itemType.forEach(item->{
                        JSONObject itemObj = (JSONObject)item;
                        ThirdItemTaskTypes tTaskTypes  = new ThirdItemTaskTypes();
                        tTaskTypes.setBusinessId(businessId);
                        tTaskTypes.setParkId(Long.valueOf(parkId));
                        String itemTypeId = itemObj.getString("itemTypeId");//项目类型编号
                        String itemTypeName = itemObj.getString("itemTypeName");//项目类型名称
                        String invoiceOneObjectName = itemObj.getString("invoiceOneObjectName");//一级开票类目
                        tTaskTypes.setItemType(itemTypeId);
                        tTaskTypes.setItemTypeName(itemTypeName);
                        tTaskTypes.setInvoiceOneName(invoiceOneObjectName);
                        JSONArray taskType = itemObj.getJSONArray("taskType");//任务类型
                        if(taskType != null){
                            taskType.forEach(task->{
                                log.info("查询企业的税源地信息结果task:{}", JSON.toJSONString(task));
                                JSONObject taskObj = (JSONObject)task;
                                String taskTypeId = taskObj.getString("taskTypeId");//任务类型编号
                                String taskTypeName = taskObj.getString("taskTypeName");//任务类型名称
                                String invoiceTwoObjectName = taskObj.getString("invoiceTwoObjectName");//一级开票类目*二级开票类目
                                tTaskTypes.setTaskType(taskTypeId);
                                tTaskTypes.setTaskTypeName(taskTypeName);
                                tTaskTypes.setInvoiceTwoName(invoiceTwoObjectName);
                            });
                        }
                        itemTaskTypess.add(tTaskTypes);
                    });
                    if(!itemTaskTypess.isEmpty()){
                        log.info("查询企业[{}]的税源地信息结果taskType:{}", businessId, JSON.toJSONString(itemTaskTypess));
                        this.thirdItemTaskTypesMapper.insertBatch(itemTaskTypess);
                    }
                }
            }
            }

        return true;
    }

    @Override
    public Boolean queryBatchSel(BusMerchant merchant, SysSyd syd, MerTask task, MerBill bill, List<MerBillDetail> detail) {

        XyjConfig config = getXyjAppInfo(syd.getId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessId", merchant.getBusinessId());
        jsonObject.put("taskType", task.getTaskId());
        jsonObject.put("outBatchNo",bill.getId());

        String sendMsg = this.createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(), jsonObject.toJSONString());
        Log.info("查询任务认领参数:{}", sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/recruit/queryBatch",sendMsg);
        BaseDataVo vo = this.decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        if(vo.getData() != null){
            JSONObject  resultJSON = (JSONObject)vo.getData();
            JSONArray array = resultJSON.getJSONArray("rows");
            detail.forEach(item->{
                array.forEach(row->{
                    JSONObject rowObj = (JSONObject)row;
                    String idno = rowObj.getString("idno");
                    String status = rowObj.getString("status");//1-认领成功，0-认领失败
                    String msg = rowObj.getString("msg");//认领失败原因
                    if(item.getCardId().equals(idno)){
                        if("1".equals(status)){
                            this.merBillDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                                .eq(MerBillDetail::getId,item.getId())
                                .set(MerBillDetail::getThridRecruit,1)
                            );
                        }else if("0".equals(status)){
                            this.merBillDetailMapper.update(new LambdaUpdateWrapper<MerBillDetail>()
                                .eq(MerBillDetail::getId,item.getId())
                                .set(MerBillDetail::getThridRecruit,0)
                                .set(MerBillDetail::getThridRecruitReason,msg)
                            );
                        }
                    }
                });
            });
        }
        return true;
    }

    @Override
    public Boolean settleQueryBatchSel(BusMerchant merchant, SysSyd syd, MerBill bill, List<MerBillDetail> detail) {
        XyjConfig config = getXyjAppInfo(syd.getId());

        JSONObject jsonObject = new JSONObject();

        jsonObject.put("businessId", merchant.getBusinessId());
        jsonObject.put("outBatchNo",bill.getId());
        String sendMsg = this.createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(), jsonObject.toJSONString());
        Log.info("查询结算参数:{}", sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/settle/queryBatch",sendMsg);
        BaseDataVo vo = this.decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        Log.info("查询结算结果:{}", JSON.toJSONString(vo));
        if(vo.getData() != null){
            JSONObject  resultJSON = (JSONObject)vo.getData();
            JSONArray freelancers = resultJSON.getJSONArray("freelancers");
            freelancers.forEach(item->{
                JSONObject itemObj = (JSONObject)item;
                String outSeqNo = itemObj.getString("outSeqNo");//
                String seqNo = itemObj.getString("seqNo");//seqNo
                Long settleFee = itemObj.getLong("settleFee");//结算金额
                Long serviceFee = itemObj.getLong("serviceFee");//服务费
                String status = itemObj.getString("status");//支付状态 0-失败，1-成功，2-支付中
                String msg = itemObj.getString("msg");//失败原因
                String remark = itemObj.getString("remark");//备注
                String payTime = itemObj.getString("payTime");//支付时间yyyy-MM-dd HH:mm:ss

                //业务处理


            });

        }
        return true;
    }

    @Override
    public void rechargeCallback(BaseDataVo bdvo) {
        Log.info("充值回调:{}", JSON.toJSONString(bdvo));

        if(bdvo.getData() != null){
            JSONObject jsonObject = (JSONObject)bdvo.getData();
            String businessId = jsonObject.getString("businessId");//商户编号
            String acctNo = jsonObject.getString("acctNo");//商户号
            Long dealFee = jsonObject.getLong("dealFee");//充值金额
            //01 充值 //02 提现 03 结算服务费 04 结算佣金 06 异名充值 08 发放退款 14 结算银行退汇
            String dealType = jsonObject.getString("dealType");//入账类型
            String dealTime = jsonObject.getString("dealTime");//入账时间
            String counterpartyAcctNo = jsonObject.getString("counterpartyAcctNo");//对方账号
            String counterpartyAcctName = jsonObject.getString("counterpartyAcctName");//对方账户名称
            String counterpartyBankName = jsonObject.getString("counterpartyBankName");//对方银行名称
            String dealId = jsonObject.getString("dealId");//交易流水号
            Long parkId = jsonObject.getLong("parkId");
            String parkName = jsonObject.getString("parkName");//税源地名称
            String remark = jsonObject.getString("remark");//备注
            //业务处理
        }
    }

    @Override
    public Boolean settleRetreat(BusMerchant merchant,Long sydId,String startTime,String endTime) {

        XyjConfig config = getXyjAppInfo(sydId);

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessId", merchant.getBusinessId());
        jsonObject.put("startDate",startTime);
        jsonObject.put("endDate",endTime);

        String sendMsg = this.createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(), jsonObject.toJSONString());
        Log.info("当零工有退款或者银行退汇等退票情况时进行查询:{}", sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/settle/queryRetreat",sendMsg);
        BaseDataVo vo = this.decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        Log.info("当零工有退款或者银行退汇等退票情况时进行查询 result:{}", JSON.toJSONString(vo));
        if(vo.getData() != null){
            JSONArray  resultJSONArray = (JSONArray)vo.getData();

            resultJSONArray.forEach(item->{
                JSONObject itemObj = (JSONObject)item;
                Long parkId = itemObj.getLong("parkId");
                String businessId = itemObj.getString("businessId");//企业编码
                String acctNo = itemObj.getString("acctNo");//支付账户
                String outBatchNo = itemObj.getString("outBatchNo");//原批次号
                String outSeqNo = itemObj.getString("outSeqNo");//原批次内序号
                Integer type = itemObj.getInteger("type");//类型1退款2退汇
                String idNo = itemObj.getString("idNo");
                String bankNo = itemObj.getString("bankNo");
                String msg = itemObj.getString("msg");
                String refundTime = itemObj.getString("refundTime");
                Long settleFee = itemObj.getLong("settleFee");//退回金额（单位分，负数）
                Long serviceFee = itemObj.getLong("serviceFee");//服务费
                String serviceRate = itemObj.getString("serviceRate");//服务费率（小数）

                //处理业务

            });

        }



        return null;
    }

    @Override
    @Transactional
    public void invoiceCallback(BaseDataVo bdvo, Long sydId) {
        Log.info("发票回调:{}", JSON.toJSONString(bdvo));
        if(bdvo.getData() != null){
            JSONObject jsonObject = (JSONObject)bdvo.getData();
            String outOrderNo = jsonObject.getString("outOrderNo");//商户订单号
            Long invoiceTotalFee = jsonObject.getLong("invoiceTotalFee");//发票申请单号
            //状态 01-待审核，02-审核通过(待开票)，03-驳回作废，04-已开票，05-作废重开 06-待开票，已申请在线开票，07-已撤回
            String status = jsonObject.getString("status");//发票状态 0-失败，1-成功，2-支付中
            String message = jsonObject.getString("message");
            if("02".equals(status)){
                this.merInvoiceMapper.update(new LambdaUpdateWrapper<MerInvoice>()
                    .eq(MerInvoice::getId,Long.valueOf(outOrderNo))
                    .set(MerInvoice::getStatus,1));
            }else if("04".equals(status)){

                JSONArray invoices = jsonObject.getJSONArray("invoices");
                this.merInvoiceMapper.update(new LambdaUpdateWrapper<MerInvoice>()
                    .eq(MerInvoice::getId,Long.valueOf(outOrderNo))
                    .set(MerInvoice::getStatus,2));
                List<MerInvoiceDetail> invoiceDetailsList = new ArrayList<>();
                invoices.forEach(item->{
                    JSONObject itemObj = (JSONObject)item;
                    String invoiceTotalFee1 = itemObj.getString("invoiceTotalFee");
                    String invoiceUrl = itemObj.getString("invoiceUrl");
                    String invoiceNum = itemObj.getString("invoiceNum");
                    MerInvoiceDetail invoiceDetail = new MerInvoiceDetail();
                    invoiceDetail.setInvId(Long.valueOf(outOrderNo));
                    invoiceDetail.setInvAmount(new BigDecimal(invoiceTotalFee1).multiply(new BigDecimal("100")).longValue());
                    invoiceDetail.setAddTime(new Date());
                    invoiceDetail.setDetailNo(invoiceNum);
                    invoiceDetail.setInvPic(invoiceUrl);
                    invoiceDetailsList.add(invoiceDetail);
                });

                if(!invoiceDetailsList.isEmpty()){
                    this.merInvoiceDetailMapper.insertBatch(invoiceDetailsList);
                }

            }else if("03".equals(status)){
                this.merInvoiceMapper.update(new LambdaUpdateWrapper<MerInvoice>()
                    .eq(MerInvoice::getId,Long.valueOf(outOrderNo))
                    .set(MerInvoice::getStatus,4)
                    .set(MerInvoice::getCancelReason,message));
            }
        }
    }

    @Override
    public Boolean taxpayDownLoad(BusMerchant merchant, SysSyd syd, String month) {

        List<MerTaxRecordsVo> recordList = this.merTaxRecordsMapper.selectVoList(new LambdaQueryWrapper<MerTaxRecords>()
            .eq(MerTaxRecords::getMerId,merchant.getId())
            .eq(MerTaxRecords::getMonth,month));
        if(recordList.isEmpty()){
            return true;
        }
        XyjConfig config = getXyjAppInfo(syd.getId());
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("businessId", merchant.getBusinessId());
        jsonObject.put("date",month);
        String sendMsg = this.createSendMsg(config.getAppid(), config.getOtherPublicKey(), config.getMyPrivateKey(), jsonObject.toJSONString());
        Log.info("下载完税证明:{}", sendMsg);
        String result = HttpUtil.post(config.getBaseUrl()+"/interface/taxpay/proveInfo",sendMsg);
        BaseDataVo vo = this.decryptAndVerify(config.getOtherPublicKey(), config.getMyPrivateKey(), result);
        Log.info("下载完税证明 result:{}", JSON.toJSONString(vo));
        if(vo.getData() != null){
            JSONArray  resultJSONArray = (JSONArray)vo.getData();
            resultJSONArray.forEach(item->{
                JSONObject itemObj = (JSONObject)item;
                String parkName = itemObj.getString("parkName");
                String invoiceUrl = itemObj.getString("invoiceUrl");
                for(MerTaxRecordsVo record:recordList){
                    SysSyd syd1 = this.sysSydMapper.selectById(record.getSydId());
                    if(parkName.equals(syd1.getGsmc())){
                        this.merTaxRecordsMapper.update(new LambdaUpdateWrapper<MerTaxRecords>()
                            .eq(MerTaxRecords::getId,record.getId())
                            .set(MerTaxRecords::getTaxFile,invoiceUrl)
                            .set(MerTaxRecords::getTaxStatus,1));
                    }
                }
            });
        }
        return true;
    }
}
