package com.jeequan.jeepay.thirdparty.channel.kqpay;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.converter.MchInfoConverter;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.MchApplyment;
import com.jeequan.jeepay.core.entity.MchInfo;
import com.jeequan.jeepay.core.entity.MchSubInfo;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.paychannel.IIsvmchApplymentService;
import com.jeequan.jeepay.core.model.applyment.ApplymentBasicInfo;
import com.jeequan.jeepay.core.model.applyment.ApplymentSignInfo;
import com.jeequan.jeepay.core.model.applyment.KqpayApplymentInfo;
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.oauth2.AlipayOauth2Params;
import com.jeequan.jeepay.core.model.oauth2.WxpayOauth2Params;
import com.jeequan.jeepay.core.model.params.kqpay.KqpayIsvParams;
import com.jeequan.jeepay.db.entity.MchSubInfoEntity;
import com.jeequan.jeepay.service.impl.MchSubInfoService;
import com.jeequan.jeepay.service.impl.SysConfigService;
import com.jeequan.jeepay.thirdparty.channel.kqpay.model.KqpayResp;
import com.jeequan.jeepay.thirdparty.channel.kqpay.util.KqpayConst;
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.Future;
import java.util.function.Consumer;

/**
 * 快钱商户入网审批流程
 * 调用BS008，获取个人信息同意授权书等官方电子版数据
 * 新商户进件申请成功，此时调BS002，返的是 审批中  ，
 * 审批完成后查询到的是 合同待签约（不能直接签约，需要激活快钱，签约前可以调合同查询接口，如果是0-待签约  才能调签约接口）
 * 签约完成后，调BS002  返的是 已完成，至此进件完成
 */
@Service
@Slf4j
public class KqpayMchApplymentService implements IIsvmchApplymentService<KqpayApplymentInfo> {

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private MchSubInfoService mchSubInfoService;

    @Autowired
    private MchInfoConverter mchInfoConverter;

    /**
     * 开户意愿确认, 入网前的操作
     *
     * @param mchApplyment
     */
    public void willingnessConfirm(MchApplyment mchApplyment, KqpayApplymentInfo applymentInfo, KqpayIsvParams isvParams) {
        JSONObject bizContent = new JSONObject();
        bizContent.put("legalId", applymentInfo.getIdcardNo());
        bizContent.put("legalName", applymentInfo.getIdcardName());

        if (applymentInfo.getMerchantType() != MchApplyment.MERCHANT_TYPE_PERSONAL) {
            // 营业执照信息
            bizContent.put("businessLicense", applymentInfo.getLicenseNo());
            bizContent.put("merchantType", "1");

            if (applymentInfo.getIsUncrpSett().equals("Y")) {
                bizContent.put("settleToAuth", "1");
                bizContent.put("authName", applymentInfo.getSettAccountName());
                bizContent.put("authIdCard", applymentInfo.getSettAccountIdcardNo());
            }
        } else {
            bizContent.put("merchantType", "2");
        }

        bizContent.put("merchantName", applymentInfo.getMchFullName());

        List<String> fileTypeList = new ArrayList<>();
        bizContent.put("fileTypeList", fileTypeList);
        fileTypeList.add("OPEN_ACCOUNT_WILLINGNESS_LETTER");
        fileTypeList.add("SPE_MERCH_SQSDZRGZS");
        fileTypeList.add("PERSONAL_INFORMATION_ATTORNEY");

        KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS008, isvParams, bizContent);
        JSONObject responseBody = kqpayResp.getResponseBody();

        String bizResponseCode = responseBody.getString("bizResponseCode");
        String bizResponseMessage = responseBody.getString("bizResponseMessage");

        if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
            log.info("快钱开户意愿确认接口调用失败, {}", bizResponseMessage);
            throw new BizException("快钱开户意愿确认失败, " + bizResponseMessage);
        }

        JSONArray data = responseBody.getJSONArray("data");
        mchApplyment.setChannelVar1(data.toJSONString());
    }

    /**
     * 上传图片，入网时候
     *
     * @param uploadResultMap 上传图片返回结果
     * @param imgUrl          图片链接
     * @param isvParams       通道服务商配置参数
     */
    public void uploadRequest(Map<String, Future<String>> uploadResultMap, String key, String imgUrl, KqpayIsvParams isvParams, Consumer<String> consumer) {
        // 下载文件
        if (ObjectUtils.isEmpty(imgUrl)) {
            return;
        }

        // 改为同步请求
        String fssId = KqpayKit.uploadRequest(imgUrl, isvParams);
        consumer.accept(fssId);

//        Future<String> submit = executorService.submit(() -> {
//            String fssId = KqpayKit.uploadRequest(imgUrl, isvParams);
//            consumer.accept(fssId);
//            return fssId;
//        });
//
//        uploadResultMap.put(key, submit);
    }

    @Override
    public com.jeequan.jeepay.core.entity.MchApplyment firstApplyment(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        // 直接丢到异步处理进件逻辑
        mchApplyment.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_AUDITING_WAIT);
        mchApplyment.setRemainStep((byte) 1);
        mchApplyment.setSettlementType(CS.SETTLEMENT_TYPE.T1);

        return mchApplyment;
    }


    public JSONObject getApplymentParams(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment, KqpayIsvParams isvParams) {

        String applyDetailInfo = mchApplyment.getApplyDetailInfo();

        Map<String, Future<String>> uploadResultMap = new HashMap<>();

        log.info("商户信息: {}", applyDetailInfo);
        if (applyDetailInfo == null || applyDetailInfo.isEmpty()) {
            throw new BizException("无法获取到商户信息");
        }

        KqpayApplymentInfo mchInfoSrc = JSON.parseObject(applyDetailInfo, KqpayApplymentInfo.class);

        willingnessConfirm(mchApplyment, mchInfoSrc, isvParams);

        JSONObject mchInfoDes = new JSONObject();
        mchInfoDes.put("operator", "admin");
        Assert.notNull(mchInfoSrc.getContactEmail(), "缺少电子邮箱");
        mchInfoDes.put("subBillAccount", mchInfoSrc.getContactEmail());
        // 结算信息
        mchInfoDes.put("settlementInfo", getSettlement(uploadResultMap, mchInfoSrc, isvParams));

        // 主体信息
        JSONObject subjectInfo = getSubjectInfo(uploadResultMap, mchInfoSrc, isvParams);

        mchInfoDes.put("subjectInfo", subjectInfo);

        // 经营信息
        mchInfoDes.put("storeInfo", getStoreInfo(uploadResultMap, mchInfoSrc, isvParams));

        // 套餐信息
        mchInfoDes.put("packageInfo", getPackageInfo(mchInfoSrc, mchApplyment));

        List<JSONObject> additionList = new ArrayList<>();
        mchInfoDes.put("additionList", additionList);

        JSONArray jsonArray = JSON.parseArray(mchApplyment.getChannelVar1());
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject item = jsonArray.getJSONObject(i);
            String fileName = item.getString("fileName");
            String fssId = item.getString("fssId");
            String fileType = item.getString("fileType");

            JSONObject finalAddition = new JSONObject();
            finalAddition.put("additionFssId", fssId);
            finalAddition.put("additionFileType", fileType);
            finalAddition.put("additionRemark", fileName);
            finalAddition.put("extName", "jpg");
            additionList.add(finalAddition);
        }

        // 开户意愿函走电子协议
//        if (!ObjectUtils.isEmpty(mchInfoSrc.getOpenAccountWillingnessLetter())) {
//            JSONObject finalAddition = new JSONObject();
//            uploadRequest(uploadResultMap, "OPEN_ACCOUNT_WILLINGNESS_LETTER", mchInfoSrc.getOpenAccountWillingnessLetter(), isvParams, s -> {
//                finalAddition.put("additionFssId", s);
//            });
//            finalAddition.put("additionFileType", "OPEN_ACCOUNT_WILLINGNESS_LETTER");
//            finalAddition.put("additionRemark", "开户意愿确认函");
//            finalAddition.put("extName", "jpg");
//            additionList.add(finalAddition);
//        }
        // 电子协议
//        if ("C".equals(mchInfoSrc.getSettAccountType())) {
//            // 个人信息单独同意授权书
//            JSONObject finalAddition2 = new JSONObject();
//            uploadRequest(uploadResultMap, "PERSONAL_INFORMATION_ATTORNEY", mchInfoSrc.getPersonalInformationAttorney(), isvParams, s -> {
//                finalAddition2.put("additionFssId", s);
//            });
//            finalAddition2.put("additionFileType", "PERSONAL_INFORMATION_ATTORNEY");
//            finalAddition2.put("additionRemark", "个人信息单独同意授权书");
//            finalAddition2.put("extName", "jpg");
//            additionList.add(finalAddition2);
//        }

//        uploadResultMap.forEach((key, value) -> {
//            try {
//                value.get();
//            } catch (InterruptedException | ExecutionException e) {
//                log.info("上传图片异常", e);
//                throw new BizException("上传图片异常");
//            }
//        });

        return mchInfoDes;
    }

    /**
     * 主体信息
     */
    private JSONObject getSubjectInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
        JSONObject subjectInfo = new JSONObject();

        subjectInfo.put("merchantShortName", mchInfoSrc.getMchShortName());
        if (mchInfoSrc.getMerchantType() == 1) {
            subjectInfo.put("subjectType", "0");
        } else if (mchInfoSrc.getMerchantType() == 2) {
            subjectInfo.put("subjectType", "5");
        } else {
            subjectInfo.put("subjectType", "1");
        }

        // 主体信息——营业执照信息
        if (mchInfoSrc.getMerchantType() != com.jeequan.jeepay.core.entity.MchApplyment.MERCHANT_TYPE_PERSONAL) {
            subjectInfo.put("businessLicenseInfo", getBusinessLicenseInfo(uploadResultMap, mchInfoSrc, isvParams));
        }

        if (com.jeequan.jeepay.core.entity.MchApplyment.MERCHANT_TYPE_ENTERPRISE == mchInfoSrc.getMerchantType()) {
            subjectInfo.put("accOpenInfo", getAccOpenInfo(uploadResultMap, mchInfoSrc, isvParams));
        }

        // 法人信息
        subjectInfo.put("identityInfo", getIdentityInfo(uploadResultMap, mchInfoSrc, isvParams));
        return subjectInfo;
    }

    private JSONObject getAccOpenInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
        JSONObject accOpenInfo = new JSONObject();

        Assert.notEmpty(mchInfoSrc.getCompanyAccountLicenseImg(), "对公结算, 开户许可证不能为空");
        // 开户凭证
        uploadRequest(uploadResultMap, "accOpenFssId", mchInfoSrc.getCompanyAccountLicenseImg(), isvParams, s -> accOpenInfo.put("accOpenFssId", s));
        accOpenInfo.put("accOpenCode", mchInfoSrc.getAccOpenCode());
        accOpenInfo.put("accOpenPeriodBegin", mchInfoSrc.getAccOpenPeriodBegin());
        accOpenInfo.put("accOpenPeriodEnd", mchInfoSrc.getAccOpenPeriodEnd());
        return accOpenInfo;
    }

    private JSONObject getBusinessLicenseInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
        JSONObject businessLicenseInfo = new JSONObject();
        businessLicenseInfo.put("businessRegno", mchInfoSrc.getLicenseNo());
        businessLicenseInfo.put("merchantName", mchInfoSrc.getMchFullName());
        businessLicenseInfo.put("legalName", mchInfoSrc.getIdcardName());
        uploadRequest(uploadResultMap, "fssId", mchInfoSrc.getLicenseImg(), isvParams, s -> businessLicenseInfo.put("fssId", s));
        businessLicenseInfo.put("constraintBusiness", mchInfoSrc.getLicenseScope());
        businessLicenseInfo.put("areaCode", mchInfoSrc.getAreaCode().getString(2));
        businessLicenseInfo.put("address", mchInfoSrc.getLicenseAddress());
        businessLicenseInfo.put("handleDate", mchInfoSrc.getLicenseEffectBegin());
        if (ApplymentBasicInfo.DATE_FOREVER_VAL.equals(mchInfoSrc.getLicenseEffectEnd())) {
            businessLicenseInfo.put("cancelDate", "9999-12-31");
        } else {
            businessLicenseInfo.put("cancelDate", mchInfoSrc.getLicenseEffectEnd());
        }
        return businessLicenseInfo;
    }

    /**
     * 经营信息
     */
    private JSONObject getStoreInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
        JSONObject storeInfo = new JSONObject();

        storeInfo.put("storeName", mchInfoSrc.getMchFullName());
        storeInfo.put("areaCode", mchInfoSrc.getAreaCode().getString(2));
        storeInfo.put("address", mchInfoSrc.getAddress());
        storeInfo.put("outStoreName", mchInfoSrc.getMchShortName());

        // 经营图片
        uploadRequest(uploadResultMap, "headFssId", mchInfoSrc.getStoreOuterImg(), isvParams, s -> storeInfo.put("headFssId", s));

        uploadRequest(uploadResultMap, "cashierFssId", mchInfoSrc.getStoreCashierImg(), isvParams, s -> storeInfo.put("cashierFssId", s));

        uploadRequest(uploadResultMap, "inDoorFssId", mchInfoSrc.getStoreInnerImg(), isvParams, s -> storeInfo.put("inDoorFssId", s));

//        String cashierFssId = uploadRequest(mchInfoSrc.getStoreOuterImg(), mchApplyment.getIsvNo());
//        storeInfo.put("headFssId", cashierFssId);
//        String cashierFssId = uploadRequest(mchInfoSrc.getStoreCashierImg(), mchApplyment.getIsvNo());
//        storeInfo.put("cashierFssId", cashierFssId);
//        String inDoorFssId = uploadRequest(mchInfoSrc.getStoreInnerImg(), mchApplyment.getIsvNo());
//        storeInfo.put("inDoorFssId", inDoorFssId);
        return storeInfo;
    }

    /**
     * 法人信息
     */
    private JSONObject getIdentityInfo(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
        JSONObject identityInfo = new JSONObject();
        identityInfo.put("telephone", mchInfoSrc.getContactPhone());
        identityInfo.put("idType", "1");
        if (mchInfoSrc.getMerchantType() == com.jeequan.jeepay.core.entity.MchApplyment.MERCHANT_TYPE_PERSONAL) {
            identityInfo.put("merchantName", mchInfoSrc.getAddress() + mchInfoSrc.getIdcardName() + mchInfoSrc.getMchShortName());
            identityInfo.put("address", mchInfoSrc.getAddress());
            identityInfo.put("areaCode", mchInfoSrc.getAreaCode().getString(2));
            identityInfo.put("constraintBusiness", mchInfoSrc.getLicenseScope());
        }

        JSONObject idCardInfo = new JSONObject();
        identityInfo.put("idCardInfo", idCardInfo);
        idCardInfo.put("idCardName", mchInfoSrc.getIdcardName());
        idCardInfo.put("idCardNumber", mchInfoSrc.getIdcardNo());
        idCardInfo.put("beginDate", mchInfoSrc.getIdcardEffectBegin());
        if (ApplymentBasicInfo.DATE_FOREVER_VAL.equals(mchInfoSrc.getIdcardEffectEnd())) {
            idCardInfo.put("expireDate", "9999-12-31");
        } else {
            idCardInfo.put("expireDate", mchInfoSrc.getIdcardEffectEnd());
        }
        // 法人身份证图片
        uploadRequest(uploadResultMap, "cardPersonFssId", mchInfoSrc.getIdcard1Img(), isvParams, s -> idCardInfo.put("cardPersonFssId", s));

        uploadRequest(uploadResultMap, "cardNationalFssId", mchInfoSrc.getIdcard2Img(), isvParams, s -> idCardInfo.put("cardNationalFssId", s));
//        String cardPersonFssId = uploadRequest(mchInfoSrc.getIdcard1Img(), mchApplyment.getIsvNo());
//        idCardInfo.put("cardPersonFssId", cardPersonFssId);
//        String cardNationalFssId = uploadRequest(mchInfoSrc.getIdcard2Img(), mchApplyment.getIsvNo());
//        idCardInfo.put("cardNationalFssId", cardNationalFssId);

        if ("Y".equals(mchInfoSrc.getIsUncrpSett())) {
            JSONObject authorizerInfo = new JSONObject();
            identityInfo.put("authorizerInfo", authorizerInfo);
            authorizerInfo.put("authName", mchInfoSrc.getSettAccountName());
            authorizerInfo.put("authIdCard", mchInfoSrc.getSettAccountIdcardNo());
            authorizerInfo.put("beginDate", mchInfoSrc.getSettAccountIdcardEffectBegin());
            if (ApplymentBasicInfo.DATE_FOREVER_VAL.equals(mchInfoSrc.getSettAccountIdcardEffectEnd())) {
                authorizerInfo.put("expireDate", "9999-12-31");
            } else {
                authorizerInfo.put("expireDate", mchInfoSrc.getSettAccountIdcardEffectEnd());
            }
            authorizerInfo.put("authName", mchInfoSrc.getSettAccountName());
            // 上传结算人身份证
            uploadRequest(uploadResultMap, "authPersonFssId", mchInfoSrc.getSettAccountIdcard1Img(), isvParams, s -> authorizerInfo.put("authPersonFssId", s));
            uploadRequest(uploadResultMap, "authNationalFssId", mchInfoSrc.getSettAccountIdcard2Img(), isvParams, s -> authorizerInfo.put("authNationalFssId", s));
//            String authPersonFssId = uploadRequest(mchInfoSrc.getSettAccountIdcard1Img(), mchApplyment.getIsvNo());
//            authorizerInfo.put("cardPersonFssId", authPersonFssId);
//            String authNationalFssId = uploadRequest(mchInfoSrc.getSettAccountIdcard2Img(), mchApplyment.getIsvNo());
//            authorizerInfo.put("cardNationalFssId", authNationalFssId);

            authorizerInfo.put("authTel", mchInfoSrc.getBankMobile());
            // 授权证明
            uploadRequest(uploadResultMap, "authFssId", mchInfoSrc.getPersonalInformationAttorney(), isvParams, s -> authorizerInfo.put("authFssId", s));
        }

        return identityInfo;
    }

    private JSONObject getSettlement(Map<String, Future<String>> uploadResultMap, KqpayApplymentInfo mchInfoSrc, KqpayIsvParams isvParams) {
        JSONObject settlementInfo = new JSONObject();

        settlementInfo.put("settlePan", mchInfoSrc.getSettAccountNo());
        settlementInfo.put("bankName", mchInfoSrc.getSettAccountBankName());
        settlementInfo.put("branchName", mchInfoSrc.getSettAccountBankBranchName());
        settlementInfo.put("areaCode", mchInfoSrc.getSettAccountBankBranchAreaCode().getString(2));
        if ("Y".equals(mchInfoSrc.getIsUncrpSett())) {
            // 非法人结算
            settlementInfo.put("accountName", mchInfoSrc.getSettAccountName());
            settlementInfo.put("bankMobilePhone", mchInfoSrc.getBankMobile());
        } else {
            settlementInfo.put("bankMobilePhone", mchInfoSrc.getLegalPersonPhone());
            String accountName = "C".equals(mchInfoSrc.getSettAccountType()) ? mchInfoSrc.getIdcardName() : mchInfoSrc.getMchFullName();
            settlementInfo.put("accountName", accountName);
        }

        if ("C".equals(mchInfoSrc.getSettAccountType())) {
            if ("Y".equals(mchInfoSrc.getIsUncrpSett())) {
                // 授权人结算
                settlementInfo.put("settleAcctType", "2");
            } else {
                // 法人对私结算
                settlementInfo.put("settleAcctType", "1");
            }
            // 对私上传结算卡
            String cardFssId = KqpayKit.uploadRequest(mchInfoSrc.getSettAccountLicenseImg(), isvParams);
            settlementInfo.put("cardFssId", cardFssId);
//            uploadRequest(uploadResultMap, "cardFssId", mchInfoSrc.getSettAccountLicenseImg(), isvParams, s -> settlementInfo.put("cardFssId", s));
        } else {
            // 对公，开户许可证在主体信息中已经上传
            settlementInfo.put("settleAcctType", "0");
        }

        return settlementInfo;
    }

    /**
     * 【微信】
     * 微信商户号ID（wechatMchID）：1502807381（快钱固定值）
     * 微信公众号ID（wechatAppID）：wxc81c4ae33fe525f0（快钱固定值）
     * 微信渠道号ID（wechatChannelID）：销售前缘申请提供，示例：178354903
     * 微信关联appId（wechatSubAppId）：商户微信应用id，示例：wx9a9e46c300ca733e
     * 微信支付目录(wechatJsapi)：商户支付目录地址，示例：https://www.99bill.com/
     * 【支付宝】
     * 支付宝APPID（aliAppID）：1266000048120000 （快钱固定值）
     * 支付宝PID（aliSource）：2088821475893827（快钱固定值）
     * 支付宝SOURCE（aliPid）：2088821475893827（可以使用快钱的SOURCE或商户自己的）
     */
    private JSONObject getPackageInfo(KqpayApplymentInfo kqpayApplymentInfo, com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        Byte merchantType = kqpayApplymentInfo.getMerchantType();
        JSONObject packInfo = new JSONObject();

        KqpayConst.Package usePackage = merchantType == 1 ? KqpayConst.Package.MICRO : KqpayConst.Package.COMPANY_AUTO_ACTIVATION;
        packInfo.put("packageCode", usePackage.getCode());

        JSONObject parameter = new JSONObject();
        packInfo.put("packageParameter", parameter);
        parameter.put("mcc", kqpayApplymentInfo.getMccCode());

        BigDecimal bigDecimal100 = new BigDecimal("100");

        List<PaywayFee> paywayFeeList = kqpayApplymentInfo.getPaywayFeeList();
        if (CollUtil.isEmpty(paywayFeeList)) {
            throw new BizException("缺少商户费率信息");
        }
        paywayFeeList.forEach(item -> {
            if (item.getWayCode().equals(CS.PAY_WAY_CODE.ALI_JSAPI)) {
                parameter.put("zhifubaoRate", item.getFeeRate().multiply(bigDecimal100).stripTrailingZeros().toPlainString());
            }

            if (item.getWayCode().equals(CS.PAY_WAY_CODE.ALI_JSAPI)) {
                parameter.put("weixinRate", item.getFeeRate().multiply(bigDecimal100).stripTrailingZeros().toPlainString());
            }

            if (item.getWayCode().equals(CS.PAY_WAY_CODE.YSF_JSAPI)) {
                String feeType = item.getFeeType();
                Long maxFee = item.getMaxFee();
                // 借记卡费率上限
                parameter.put("cuDebitMaxFee", BigDecimal.valueOf(maxFee).divide(bigDecimal100, 2, RoundingMode.DOWN).stripTrailingZeros().toPlainString());
                if (PaywayFee.FEE_TYPE_LEVEL.equals(feeType)) {
                    // 分级
                    item.getLevelList().forEach(levelItem -> {
                        if (Objects.equals(levelItem.getMinFee(), 100000L)) {
                            // 银联借记卡大额费率
                            BigDecimal feeRate = levelItem.getFeeRate();
                            parameter.put("cuRateDebit", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
                        }
                    });
                    // 贷记卡, 不支持小微
                    item.getCreditCardPaywayFee().getLevelList().forEach(levelItem -> {
                        BigDecimal feeRate = levelItem.getFeeRate();
                        if (Objects.equals(levelItem.getMinFee(), 100000L)) {
                            // 银联贷记卡大额费率
                            parameter.put("cuRateCredit", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
                        } else {
                            // 银联贷记卡小额费率
                            parameter.put("smallDiscountRate", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
                        }
                    });
                }
            }

            // 线上费率
            if (item.getWayCode().equals(CS.PAY_WAY_CODE.SCAN)) {
                BigDecimal feeRate = item.getFeeRate();
                parameter.put("zhifubaoRate", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
                parameter.put("weixinRate", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());

                // 银联借记卡大额费率
                parameter.put("cuRateDebit", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
                // 小额优惠费率
                parameter.put("smallDiscountRate", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());
                //
                parameter.put("cuRateCredit", feeRate.multiply(bigDecimal100).stripTrailingZeros().toPlainString());

                parameter.put("cuDebitMaxFee", "20.0");
            }
        });

        // 轻快付
        parameter.put("terminalQkf", "1");
        parameter.put("isWechatAppletPay", "1");

        String paySiteUrl = sysConfigService.getDBApplicationConfig().getPaySiteUrl();
        ;
        if (paySiteUrl == null || paySiteUrl.isEmpty()) {
            throw new BizException("未获取到支付网关信息");
        }

        // 微信配置
        WxpayOauth2Params wxpayOauth2Params = (WxpayOauth2Params) configContextQueryService.queryIsvOauth2Params(mchApplyment.getIsvNo(), CS.IF_CODE.WXPAY);
        if (wxpayOauth2Params == null) {
            throw new BizException("服务商未配置微信oauth信息");
        }

        parameter.put("wechatAppID", "wxc81c4ae33fe525f0");
        parameter.put("wechatMchID", "1502807381");
        parameter.put("wechatChannelID", "191695524");

        String liteAppId = wxpayOauth2Params.getLiteAppId();
        if (ObjectUtils.isEmpty(liteAppId)) {
            parameter.put("wechatSubAppId", wxpayOauth2Params.getAppId());
        } else {
            parameter.put("wechatSubAppId", wxpayOauth2Params.getAppId() + ";" + wxpayOauth2Params.getLiteAppId());
        }
        parameter.put("wechatJsapi", paySiteUrl + "/");

        // 支付宝配置
        AlipayOauth2Params alipayOauth2Params = (AlipayOauth2Params) configContextQueryService.queryIsvOauth2Params(mchApplyment.getIsvNo(), CS.IF_CODE.ALIPAY);
        if (alipayOauth2Params == null) {
            throw new BizException("服务商未配置微信oauth信息");
        }

        parameter.put("isAlipayAppletPay", "1");
        parameter.put("aliAppID", "1266000048120000");
        parameter.put("aliSource", "2088821475893827");
        parameter.put("aliPid", "2088821475893827");

        return packInfo;
    }

    @Override
    public com.jeequan.jeepay.core.entity.MchApplyment rejectModify(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        return firstApplyment(mchApplyment);
    }

    @Override
    public com.jeequan.jeepay.core.entity.MchApplyment replenishInfo(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        return null;
    }

    @Override
    public com.jeequan.jeepay.core.entity.MchApplyment query(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        log.info("快钱商户入网状态查询, 商户号为{}", mchApplyment.getApplyId());
        com.jeequan.jeepay.core.entity.MchApplyment result = new com.jeequan.jeepay.core.entity.MchApplyment();
        result.setApplyId(mchApplyment.getApplyId());
        result.setState(mchApplyment.getState());
        JSONObject bizJSON = new JSONObject();
        String orderId = mchApplyment.getChannelApplyNo();
        bizJSON.put("orderId", orderId);

        KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);

        MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
        mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
        mchAppConfigContext.setMchApplyment(mchApplyment);
        KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS002, isvParams, bizJSON);
        JSONObject responseBody = kqpayResp.getResponseBody();
        String bizResponseCode = responseBody.getString("bizResponseCode");
        String bizResponseMessage = responseBody.getString("bizResponseMessage");
        if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
            log.info("快钱查询商户审核状态失败, {}", bizResponseMessage);
            return mchApplyment;
        }

        String status = responseBody.getString("status");
        String comments = responseBody.getString("comments");
        JSONObject openResult = responseBody.getJSONObject("openResult");

        if ("AUDITING".equals(status)) {
            return result;
        }

        result.setApplyErrorInfo(comments);
        if ("TO_BE_SIGNED".equals(status)) {

            int allowSign = isAllowSign(mchApplyment);
            // 待签约
            if (allowSign == 1) {
                // 可以签约的话，直接签约之后再查询
                signApply(mchApplyment);

                return query(mchApplyment);
            }

            // 待激活
            if (allowSign == 2) {
                result.setState(MchApplyment.STATE_WAIT_SIGN);
                return result;
            }

            return result;
        }

        if ("TO_BE_REAUDITED".equals(status)) {
            if (openResult != null) {
                result.setChannelMchNo(openResult.getString("subMerchantId"));
                result.setSuccResParameter(openResult.toString());
                subMchColl(mchApplyment, openResult);
            }
            result.setState(MchApplyment.STATE_SUCCESS_NEED_SECOND_VERIFY);

            return result;
        }

        if ("REJECTED".equals(status)) {
            result.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_REJECT_WAIT_MODIFY);
            return result;
        }

        if ("FINISHED".equals(status)) {
            if (openResult != null) {
                result.setChannelMchNo(openResult.getString("subMerchantId"));
                result.setSuccResParameter(openResult.toString());
                subMchColl(mchApplyment, openResult);
            }
            result.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_SUCCESS);

            return result;
        }

        return result;
    }

    @Override
    public ApplymentSignInfo signInfo(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {

        return null;
    }

    @Override
    public com.jeequan.jeepay.core.entity.MchApplyment signApply(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        String orderId = mchApplyment.getChannelVar1();
        JSONObject param = new JSONObject();
        param.put("orderId", mchApplyment.getChannelApplyNo());

        KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);

        KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS004, isvParams, param);
        JSONObject responseBody = kqpayResp.getResponseBody();
        String bizResponseCode = responseBody.getString("bizResponseCode");
        String bizResponseMessage = responseBody.getString("bizResponseMessage");

        if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
            log.info("发起签约失败, {}", bizResponseMessage);
            throw new BizException(bizResponseMessage);
        }

        String authStatus = responseBody.getString("authStatus");
        if (!"1".equals(authStatus)) {
            throw new BizException("签约失败");
        } else {
            mchApplyment.setState(com.jeequan.jeepay.core.entity.MchApplyment.STATE_FINISH_SIGN);
        }

        return mchApplyment;
    }

    /**
     *
     * @param mchApplyment
     * @return 返回1，可以使用接口签约，2，需要快钱官网手动签约
     */
    public int isAllowSign(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        String orderId = mchApplyment.getChannelApplyNo();
        JSONObject param = new JSONObject();
        param.put("orderId", orderId);

        MchAppConfigContext mchAppConfigContext = new MchAppConfigContext();
        mchAppConfigContext.setMchType(MchInfo.TYPE_ISVSUB);
        mchAppConfigContext.setMchApplyment(mchApplyment);

        KqpayIsvParams isvParams = (KqpayIsvParams) configContextQueryService.queryIsvParams(mchApplyment);

        KqpayResp kqpayResp = KqpayKit.applymentRequest(KqpayConst.ReqMethod.BS003, isvParams, param);
        JSONObject responseBody = kqpayResp.getResponseBody();
        String bizResponseCode = responseBody.getString("bizResponseCode");
        String bizResponseMessage = responseBody.getString("bizResponseMessage");

        if (!KqpayConst.SUCCESS.equals(bizResponseCode)) {
            //
            log.info("查询签约状态失败, {}", bizResponseMessage);
            return 0;
        }

        JSONArray econtractList = responseBody.getJSONArray("econtractList");
        for (int i = 0; i < econtractList.size(); i++) {
            JSONObject econtract = econtractList.getJSONObject(i);

            /*
             * 0：待签约；
             * 1：签约成功；
             * 2：签约拒绝；
             * 3：快钱账户待激活；
             * 4：合同生成，待转 PDF；
             * 6：签约中；
             * 7：签约失败；
             * -1：未生成合同
             */
            if (econtract.getString("authStatus").equals("0")) {
                return 1;
            }

            if (econtract.getString("authStatus").equals("3")) {
                return 3;
            }
        }


        return 0;
    }

    @Override
    public void subMchColl(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment, Object openResult1) {
        JSONObject openResult = (JSONObject) openResult1;

        String subMerchantId = openResult.getString("subMerchantId");
        List<MchSubInfoEntity> mchSubInfoEntityList = new ArrayList<>();

        JSONArray alipayList = openResult.getJSONArray("alipayList");
        if (!CollUtil.isEmpty(alipayList)) {
            getByOpenResultItem(mchApplyment.getApplyId(), subMerchantId, "ZFB", alipayList);
        }

        JSONArray wechatList = openResult.getJSONArray("wechatList");
        if (!CollUtil.isEmpty(wechatList)) {
            getByOpenResultItem(mchApplyment.getApplyId(), subMerchantId, "WX", wechatList);
        }

    }

    public void getByOpenResultItem(String mchApplyId, String channelMchNo, String subChannelType, JSONArray subMchArr) {
        List<MchSubInfoEntity> mchSubInfoEntityList = new ArrayList<>();
        for (int i = 0; i < subMchArr.size(); i++) {
            JSONObject openResultItem = subMchArr.getJSONObject(i);
            MchSubInfoEntity entity = new MchSubInfoEntity();
            entity.setChannelMchNo(channelMchNo);
            entity.setRemark(openResultItem.getString("errorMsg"));
            entity.setSubMchId(openResultItem.getString("subMchId"));
            entity.setStatus(openResultItem.getString("status"));
            entity.setSubMchType(subChannelType);
            entity.setSubMchWay("KQ");
            entity.setMchApplyId(mchApplyId);
            entity.setMainUse(1);
            entity.setAuthStatus(MchSubInfo.AUTH_STATUS_UNKNOWN);

            try {
                mchSubInfoService.saveBatch(mchSubInfoEntityList);
            } catch (DuplicateKeyException e) {
                log.info("快钱子商户信息已存在");
            }
        }
    }


    @Override
    public void subMchColl(com.jeequan.jeepay.core.entity.MchApplyment mchApplyment) {
        query(mchApplyment);
    }
}
