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

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.diagnosis.DiagnosisUtils;
import com.alipay.api.domain.*;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.icbc.api.internal.util.internal.util.fastjson.JSON;
import com.jeequan.jeepay.converter.TransferConverter;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.TransferOrder;
import com.jeequan.jeepay.core.entity.TransferSubject;
import com.jeequan.jeepay.core.entity.TransferWallet;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.paychannel.aliaqfbiz.IAliAqfV2ApiService;
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
import com.jeequan.jeepay.core.model.params.aliaqf.AliaqfIsvParams;
import com.jeequan.jeepay.core.model.params.alipay.AlipayConfig;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.SeqKit;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.service.impl.*;
import com.jeequan.jeepay.thirdparty.channel.aliaqf.AliaqfTransferService;
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
@Slf4j
public class AliAqfV2Service implements IAliAqfV2ApiService {

    @Autowired
    private SysConfigService sysConfigService;

    @Autowired
    private TransferInterfaceConfigService transferInterfaceConfigService;

    @Autowired
    private TransferSubjectService transferSubjectService;

    @Autowired
    private TransferOrderService transferOrderService;

    @Autowired
    private TransferWalletService transferWalletService;
    @Autowired
    private ConfigContextQueryService configContextQueryService;

    @Autowired
    private RateConfigService rateConfigService;

    @Autowired
    private TransferConverter transferConverter;

    @Autowired
    private AccountInfoService accountInfoService;
    @Autowired
    private AliaqfTransferService aliaqfTransferService;

    private String getOpenCallbackUrl(String subjectId) {
        return sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/transferSubject/notify/aliaqf/" + subjectId;
    }

    /**
     * 签约
     */
    @Override
    public String userAgreementPageSign(String subId) {
        log.info("进入了支付宝签约");
        TransferSubjectEntity subjectEntity = getSubjectOne(subId);
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
        if (subjectEntity.getState() == TransferSubject.STATE_DISABLE) {
            throw new BizException("当前付款账户已被停用！");
        }

        Assert.notNull(subjectEntity.getTransApplyId(), "申请单号不能为空");

        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayUserAgreementPageSignRequest request = new AlipayUserAgreementPageSignRequest();
            AlipayUserAgreementPageSignModel model = new AlipayUserAgreementPageSignModel();
            model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
            AccessParams accessParams = new AccessParams();
            accessParams.setChannel("QRCODE");
            model.setAccessParams(accessParams);
            model.setProductCode("FUND_SAFT_SIGN_WITHHOLDING");
            model.setSignScene("INDUSTRY|SATF_ACC");
            //唯一标识，新建收款账户时生成，
            model.setExternalAgreementNo(subjectEntity.getTransApplyId());
            model.setThirdPartyType("PARTNER");
            request.setBizModel(model);

            String openCallbackUrl = getOpenCallbackUrl(subjectEntity.getTransApplyId());
            request.setNotifyUrl(openCallbackUrl);
            log.info("安全发签约回调地址：" + openCallbackUrl);
            log.info("请求报文：{}", JSONObject.toJSONString(request));
            AlipayUserAgreementPageSignResponse response = alipayClient.pageExecute(request, "get");

            String pageRedirectionData = response.getBody();

            if (response.isSuccess()) {
                log.info("安全发签约返回：" + response.getBody());
                //设置为签约中
                subjectEntity.setSignState((int) TransferSubject.SIGN_STATE_AUDITING);
                subjectEntity.setChannelVar1(pageRedirectionData);
                transferSubjectService.updateById(subjectEntity);

                return pageRedirectionData;
            } else {
                log.info("安全发签约发起请求失败");
                String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response);

                if (ObjUtil.isEmpty(diagnosisUrl)) {
                    throw new BizException(response.getSubMsg());
                }

                return diagnosisUrl;
            }

        } catch (AlipayApiException e) {
            log.error("安全发签约请求异常！");
            throw new BizException(e.getErrMsg());
        }
    }

    /**
     * 支付宝个人代扣协议查询接口
     *
     * @param
     * @return
     */
    @Override
    public JSONObject userAgreementQuery(String subId) {
        log.info("进入了支付宝个人代扣协议查询接口");
        TransferSubjectEntity subjectEntity = getSubjectOne(subId);
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
        JSONObject resut = new JSONObject();
        if (certAlipayRequest == null || subjectEntity.getTransApplyId() == null) {
            throw new BizException("未获取到当前用户相关信息！");
        }
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayUserAgreementQueryRequest request = new AlipayUserAgreementQueryRequest();

            AlipayUserAgreementQueryModel model = new AlipayUserAgreementQueryModel();
            model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
            model.setSignScene("INDUSTRY|SATF_ACC");
            //签约时传入值
            model.setExternalAgreementNo(subjectEntity.getTransApplyId());
            model.setThirdPartyType("PARTNER");
            request.setBizModel(model);
            AlipayUserAgreementQueryResponse response = alipayClient.certificateExecute(request);
            resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_user_agreement_query_response");
        } catch (Exception e) {
            log.error("支付宝个人代扣协议查询异常！",e);
            throw new BizException("支付宝个人代扣协议查询异常！");
        }
        return resut;
    }

    /**
     * 解约
     *
     * @param
     * @return
     */
    @Override
    public JSONObject userAgreementUnsign(String subId) {
        log.info("进入了支付宝个人代扣协议解约接口");
        TransferSubjectEntity subjectEntity = getSubjectOne(subId);
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
        JSONObject resut = new JSONObject();
        if (certAlipayRequest == null || subjectEntity.getTransApplyId() == null) {
            throw new BizException("未获取到当前用户相关信息！");
        }
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayUserAgreementUnsignRequest request = new AlipayUserAgreementUnsignRequest();

            AlipayUserAgreementUnsignModel model = new AlipayUserAgreementUnsignModel();
            model.setPersonalProductCode("FUND_SAFT_SIGN_WITHHOLDING_P");
            model.setSignScene("INDUSTRY|SATF_ACC");
            //签约时传入值
            model.setExternalAgreementNo(subjectEntity.getTransApplyId());
            //注意：仅异步解约需传入，其余情况无需传递本参数。
            // 解约确认: confirm
            //解约作废: invalid
            model.setOperateType("confirm");
            request.setBizModel(model);
            //request.setNotifyUrl(sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/anf/reqUnsign");
            //log.info("安全发解约回调地址：" + sysConfigService.getDBApplicationConfig().getPaySiteUrl() + "/api/anf/reqNotify");
            AlipayUserAgreementUnsignResponse response = alipayClient.certificateExecute(request);
            log.info("支付宝个人代扣协议解约返回参数：" + response.getBody());
            if (response.isSuccess()) {
                //直接就是已解约，异步返回暂时不处理
                subjectEntity.setSignState((int)TransferSubject.STATE_ENABLE_REVIEW);
                transferSubjectService.updateById(subjectEntity);
            } else {
                log.info("支付宝个人代扣协议解约失败：" + response.getSubMsg());
            }
            resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_user_agreement_unsign_response");
            subjectEntity.setChannelVar1(response.getBody());
        } catch (Exception e) {
            log.error("支付宝个人代扣协议解约异常！",e);
            throw new BizException("支付宝个人代扣协议解约异常！");
        }
        return resut;
    }

    /**
     * 资金记账本开通
     *
     * @return
     */
    @Override
    public void fundAccountbookCreate(String subId) {

        log.info("进入资金记账本开通方法！");
        TransferSubjectEntity subjectEntity = getSubjectOne(subId);
        AliaqfIsvParams isvParams = ((AliaqfIsvParams) configContextQueryService.queryTransferIsvParams(subjectEntity.getIsvNo(), CS.IF_CODE.ALIAQF));

        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
        TransferSubjectEntity transferSubject = transferSubjectService.getById(subId);

        TransferWallet transferWallet = new TransferWallet();
        AlipayFundAccountbookCreateResponse response;
        String merchantUserId = UUID.randomUUID().toString().replace("-", "");
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayFundAccountbookCreateRequest request = new AlipayFundAccountbookCreateRequest();
            AlipayFundAccountbookCreateModel model = new AlipayFundAccountbookCreateModel();
            //外部商户系统会员的唯一标识，自定义传入
            model.setMerchantUserId(merchantUserId);
            model.setMerchantUserType("BUSINESS_ORGANIZATION");
            model.setSceneCode("SATF_FUND_BOOK");
            //扩展信息： 支付宝协议号必传、企业营业执照认证号（cert_no）可不传。
            //注意：ext_info字段本质上是String类型，所以传递的是转义后的json字符串。
            //agreement_no 签约时回调返回的参数值
            JSONObject param = new JSONObject();
            param.put("agreement_no", transferSubject.getTransChannelSignNo());
            model.setExtInfo(param.toJSONString());
            request.setBizModel(model);
            response = alipayClient.certificateExecute(request);
            //处理记账本返回信息
            log.info("支付宝安全发记账本开通请求返回参数, {}", response.getBody());
            String responseBody = response.getBody();
            if (response.isSuccess()) {
                JSONObject jsonObject = JSONObject.parseObject(responseBody);
                ExtCardInfo extCardInfo = response.getExtCardInfo();
                transferSubject.setTransChannelMchNo(response.getAccountBookId());
                //记账本信息
                transferWallet.initFromSubject(transferSubject);
                transferWallet.setTransChannelMchNo(response.getAccountBookId());
                transferWallet.setWalletApplyId(model.getMerchantUserId());
                transferWallet.setExtResponse(jsonObject.toJSONString());
                transferWallet.setFeeCostType(TransferOrder.COST_TYPE_ACCOUNT);
                transferWallet.setTransIfCode(CS.IF_CODE.ALIAQF);

                isvParams.initQuota(transferWallet);

                if (extCardInfo != null) {
                    transferWallet.setExtCardInfo(JSONObject.toJSONString(response.getExtCardInfo()));
                    if ("A".equals(extCardInfo.getStatus())) {
                        transferWallet.setCardStatus(TransferWalletEntity.CARD_STATUS_NORMAL);
                    } else {
                        transferWallet.setCardStatus(TransferWalletEntity.CARD_STATUS_OTHER);
                    }
                }
                transferWalletService.save(transferConverter.toDbEntity(transferWallet));
                transferSubjectService.updateById(transferSubject);
            } else {
                log.info("资金记账本开通失败, {}", response.getSubMsg());
            }

        } catch (Exception e) {
            log.info("资金记账本开通异常", e);
        }

    }

    /**
     * 资金记账本的信息查询
     *
     * @return
     */
    @Override
    public AlipayFundAccountbookQueryResponse fundAccountbookQuery(String walletApplyId) {
        log.info("进入了支付宝资金记账本的信息查询");
        TransferWalletEntity transferWallet = transferWalletService.getByApplyId(null, walletApplyId);
        TransferSubjectEntity subjectEntity = transferSubjectService.getByApplyId(transferWallet.getTransApplyId());
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
        AlipayFundAccountbookQueryResponse response;
        if (certAlipayRequest == null || subjectEntity.getTransChannelSignNo() == null
                || subjectEntity.getTransChannelMchNo() == null) {
            throw new BizException("当前用户暂未签约或配置！");
        }

        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayFundAccountbookQueryRequest request = new AlipayFundAccountbookQueryRequest();
            AlipayFundAccountbookQueryModel model = new AlipayFundAccountbookQueryModel();
            //资金记账本id，开通时的返回值
            model.setAccountBookId(subjectEntity.getTransChannelMchNo());
            //商户会员的唯一标识 开通时自定义传入值
            model.setMerchantUserId(transferWallet.getWalletApplyId());
            model.setSceneCode("SATF_FUND_BOOK");
            //扩展信息： 支付宝协议号必传
            //注意：ext_info字段本质上是String类型，所以传递的是转义后的json字符串。
            //agreement_no 签约时回调返回的参数值
            JSONObject parm = new JSONObject();
            parm.put("agreement_no", subjectEntity.getTransChannelSignNo());
            model.setExtInfo(parm.toJSONString());
            request.setBizModel(model);

            response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                String responseBody = response.getBody();
                JSONObject jsonObject = JSONObject.parseObject(responseBody);
                JSONObject accountbook = jsonObject.getJSONObject("alipay_fund_accountbook_query_response");
                transferWallet.setAccountBookBalance(AmountUtil.convertDollar2CentLong(accountbook.getString("available_amount")));
                ExtCardInfo extCardInfo = response.getExtCardInfo();
                if (extCardInfo != null) {
                    transferWallet.setExtCardInfo(JSON.toJSONString(extCardInfo));
                    if ("A".equals(extCardInfo.getStatus())) {
                        transferWallet.setCardStatus(1);
                    } else {
                        transferWallet.setCardStatus(2);
                    }
                }
                transferWalletService.updateById(transferWallet);
            } else {
                log.error("资金记账本的信息查询失败！" + response.getSubMsg());
            }
        } catch (Exception e) {
            log.error("资金记账本的信息查询异常！",e);
            throw new BizException("资金记账本的信息查询异常！");
        }

        return response;
    }

    /**
     * 资金专款拨入（商户自身给记账本充值）
     */
    @Override
    public String transPage(String subId, String transAmount ,String transferDesc) {
        log.info("进入了支付宝资金专款拨入（商户自身给记账本充值）");
        TransferSubjectEntity subjectEntity = getSubjectOne(subId);
        String resultUrl = null;
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(subjectEntity.getIsvNo());
        Assert.notNull(subjectEntity, "付款账户不存在");

        //transferOrderService
        TransferOrderEntity transferOrder = new TransferOrderEntity();
        if (subjectEntity.getState() == TransferSubject.STATE_DISABLE) {
            throw new BizException("当前付款账户已被停用");
        }

        //获取当前时间1小时后的时间作为过期时间
        String formattedDateTime = LocalDateTime.now().plusHours(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
        Assert.notEmpty(subjectEntity.getTransChannelMchNo(), "未获取到记账本数据");
        Assert.notEmpty(subjectEntity.getTransChannelSignNo(), "未获取到签约数据");

        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayFundTransPagePayRequest request = new AlipayFundTransPagePayRequest();
            AlipayFundTransPagePayModel model = new AlipayFundTransPagePayModel();
            //商户端的唯一订单号，对于同一笔转账请求，商户需保证该订单号唯一。
            model.setOutBizNo(SeqKit.genTransOrderId());
            log.info("资金专款拨入outBizNo====================={}", model.getOutBizNo());
            //拨入总金额，单位为元，精确到小数点后两位，取值范围[0.01,9999999999999.99]
            model.setTransAmount(transAmount);
            //
            model.setProductCode("FUND_ACCOUNT_BOOK");
            //
            model.setBizScene("SATF_DEPOSIT");
            //充值订单过期时间，默认会失败
            model.setTimeExpire(formattedDateTime);
            //收款方信息
            Participant payeeInfo = new Participant();
            //记账本 id
            payeeInfo.setIdentity(subjectEntity.getTransChannelMchNo());
            payeeInfo.setIdentityType("ACCOUNT_BOOK_ID");
            //传入记账本id与场景码，不传会校验失败导致充值失败。协议字段必传。
            JSONObject parm = new JSONObject();
            parm.put("agreement_no", subjectEntity.getTransChannelSignNo());
            payeeInfo.setExtInfo(parm.toJSONString());
            model.setPayeeInfo(payeeInfo);

            request.setBizModel(model);

            AlipayFundTransPagePayResponse response = alipayClient.pageExecute(request, "GET");
            if (response.isSuccess()) {
                log.info("资金专项拨入结果：{}", response.getBody());
                resultUrl = response.getBody();
                //转账中，回调后改变状态
                transferOrder.setState(TransferOrderEntity.STATE_ING);
            } else {
                log.error("资金专项拨入失败！{}", response.getSubMsg());
                resultUrl = response.getSubMsg();
                //转账失败
                transferOrder.setState(TransferOrderEntity.STATE_FAIL);
                transferOrder.setErrCode(response.getSubCode());
                transferOrder.setErrMsg(response.getSubMsg());
            }
            //将订单信息入库
            // TODO: 2024/4/29 先做简单入库 后续完善
            transferOrder.setAmount(AmountUtil.convertDollar2CentLong(transAmount));
            transferOrder.setTransferId(model.getOutBizNo());
            transferOrder.setMchOrderNo(model.getOutBizNo());
            transferOrder.setTransferType(TransferOrderEntity.TRANSFER_TYPE_CZ);
            transferOrder.setIfCode(CS.IF_CODE.ALIAQF);
            transferOrder.setIsvNo(subjectEntity.getIsvNo());
            transferOrder.setTransferSubjectIdFq(subjectEntity.getId());
            transferOrder.setTransferSubjectIdJs(subjectEntity.getId());
            transferOrder.setMchNo(subjectEntity.getMchNo());
            transferOrder.setMchExtNo(StringUtils.isNotEmpty(subjectEntity.getMchApplyId())?subjectEntity.getMchApplyId():null);
            transferOrder.setAgentNo(subjectEntity.getAgentNo());
            transferOrder.setAccountNo(subjectEntity.getAccount());
            transferOrder.setAccountName(subjectEntity.getAccountName());
            transferOrder.setTransferDesc(transferDesc);
            transferOrderService.save(transferOrder);
        } catch (Exception e) {
            log.error("资金专项拨入异常！",e);
            throw new BizException("资金专项拨入异常!");
        }

        return resultUrl;
    }

    /**
     * 基于记账本代发
     */
    @Override
    public ChannelRetMsg transUniTransfer(TransferOrder transferOrder) {
        try {
            return aliaqfTransferService.transfer(null, transferOrder);
        } catch(Exception e) {
            log.info("支付宝安全发下发异常", e);

            return ChannelRetMsg.confirmFail(null, e.getMessage());
        }
    }

    /**
     * 账单查询
     */

    @Override
    public JSONObject bizfundagentQuery(String subId, String startTime, String endTime, String pageNo, String pageSize) {
        log.info("进入了支付宝账单查询");
        TransferSubjectEntity ersubjectEntity = getSubjectOne(subId);
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(ersubjectEntity.getIsvNo());
        JSONObject resut = new JSONObject();
        AlipayDataBillBizfundagentQueryResponse response = new AlipayDataBillBizfundagentQueryResponse();
        if ( ersubjectEntity.getTransChannelSignNo() == null || ersubjectEntity.getTransChannelMchNo() == null) {
            throw new BizException("当前付款人签约或开通记账本！");
        }
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayDataBillBizfundagentQueryRequest request = new AlipayDataBillBizfundagentQueryRequest();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("start_time", startTime);
            jsonObject.put("end_time", endTime);
            jsonObject.put("page_no", StringUtils.isEmpty(pageNo) ? "1" : pageNo);
            jsonObject.put("page_size", StringUtils.isEmpty(pageSize) ? "2000" : pageSize);
            jsonObject.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
            jsonObject.put("account_book_id", ersubjectEntity.getTransChannelMchNo());
            request.setBizContent(jsonObject.toJSONString());

            response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                log.info("安全发账单查询成功：" + response.getBody());
            } else {
                log.error("安全发账单查询失败！" + response.getSubMsg());
            }
            resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_data_bill_bizfundagent_query_response");
        } catch (Exception e) {
            resut.put("code", "99999");
            resut.put("subMsg", "安全发账单查询异常！！");
            log.error("安全发账单查询异常！",e);
        }
        return resut;
    }

    /**
     * 申请电子回单
     */

    @Override
    public JSONObject applicationForm(String subId, String transferId) {
        log.info("进入了支付宝申请电子回单");
        TransferSubjectEntity ersubjectEntity = getSubjectOne(subId);
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(ersubjectEntity.getIsvNo());
        TransferOrderEntity transferOrder = transferOrderService.getById(transferId);
        JSONObject resut = new JSONObject();
        AlipayDataBillEreceiptagentApplyResponse response;

        Assert.notNull(ersubjectEntity, "未获取到记账本数据！");
        Assert.notNull(ersubjectEntity.getTransChannelSignNo(), "记账本签约数据异常！");
        Assert.notNull(transferOrder, "未获取到订单信息！");

        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayDataBillEreceiptagentApplyRequest request = new AlipayDataBillEreceiptagentApplyRequest();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("type", "FUND_DETAIL");
            jsonObject.put("key", transferOrder.getFlowNo());
            jsonObject.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
            request.setBizContent(jsonObject.toJSONString());

            response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                log.info("申请电子回单：{}", response.getBody());
                transferOrder.setApplicationFormState(1);
                transferOrder.setApplicationFileId(response.getFileId());
                transferOrderService.updateById(transferOrder);
            } else {
                log.error("申请电子回单失败！{}", response.getSubMsg());
            }
            resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_data_bill_ereceiptagent_apply_response");
        } catch (Exception e) {
            resut.put("code", "99999");
            resut.put("subMsg", "申请电子回单异常！！");
            log.error("申请电子回单异常！",e);
        }
        return resut;
    }

    /**
     * 回单申请状态和下载地址
     */

    @Override
    public JSONObject applicationFormDownload(String subId, String transferId) {
        log.info("进入了支付宝回单申请状态和下载地址");
        TransferSubjectEntity ersubjectEntity = getSubjectOne(subId);
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(ersubjectEntity.getIsvNo());
        TransferOrderEntity transferOrder = transferOrderService.getById(transferId);
        JSONObject resut = new JSONObject();

        AlipayDataBillAccountbookereceiptQueryResponse response;
        if (ersubjectEntity.getTransChannelSignNo() == null || transferOrder == null || transferOrder.getApplicationFileId() == null) {
            throw new BizException("当前付款人不符合申请条件!");
        }

        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayDataBillAccountbookereceiptQueryRequest request = new AlipayDataBillAccountbookereceiptQueryRequest();

            JSONObject jsonObject = new JSONObject();
            jsonObject.put("file_id", transferOrder.getApplicationFileId());
            jsonObject.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
            request.setBizContent(jsonObject.toJSONString());
            response = alipayClient.certificateExecute(request);
            if (response.isSuccess()) {
                log.info("回单申请状态和下载地址返回：{}", response.getBody());
            } else {
                log.error("回单申请状态和下载地址失败！{}", response.getSubMsg());
            }
            resut = JSONObject.parseObject(response.getBody()).getJSONObject("alipay_data_bill_accountbookereceipt_query_response");
        } catch (Exception e) {
            resut.put("code", "99999");
            resut.put("subMsg", "回单申请状态和下载地址异常！！");
            log.error("回单申请状态和下载地址异常！",e);
        }
        return resut;
    }


    /**
     * 生成待发待结算信息
     *
     * @return
     */
    public String settlementData(String ersubId, List<TransferOrder> entityList) {
        String resut = "操作成功！";
        TransferSubjectEntity transferSubject = transferSubjectService.getById(ersubId);
        TransferWalletEntity transferWallet = transferWalletService.getByApplyId(transferSubject.getTransApplyId(), null);
        if (transferSubject.getState() == TransferSubject.STATE_DISABLE) {
            throw new BizException("当前付款账户已停用!");
        }
        if (ObjUtil.isEmpty(entityList)) {
            throw new BizException("收款人不能为空!");
        }
        if (transferSubject.getTransChannelMchNo() == null || transferSubject.getTransChannelSignNo() == null) {
            throw new BizException("付款账户暂未签约或开通记账本!");
        }

        Map<String, TransferSubject> map = new HashMap<>();
        List<TransferOrderEntity> dataList = new ArrayList<>();
        for (TransferOrder item: entityList) {
            TransferSubject itemJsInfo = map.get(item.getTransferSubjectIdJs());
            if (itemJsInfo == null) {
                itemJsInfo = transferSubjectService.getById(item.getTransferSubjectIdJs());
                map.put(item.getTransferSubjectIdJs(), itemJsInfo);
            }

            // ersubId:付款方id   eesubId：收款方id
            // TODO: 2024/4/30 后续完善参数
            TransferOrderEntity transferOrder = transferConverter.toDbEntity(item);
            transferOrder.setTransferId(SeqKit.genTransOrderId());
            transferOrder.setMchNo(transferSubject.getMchNo());
            transferOrder.setMchExtNo(transferSubject.getMchApplyId());
            transferOrder.setIsvNo(transferSubject.getIsvNo());
            transferOrder.setAgentNo(transferSubject.getAgentNo());
            transferOrder.setTransferSubjectIdFq(ersubId);
            transferOrder.setWalletId(transferWallet.getId());
            transferOrder.setTransferSubjectIdJs(item.getTransferSubjectIdJs());
            transferOrder.setAccountType(itemJsInfo.getAccountType());
            transferOrder.setAccountNo(itemJsInfo.getAccount());
            transferOrder.setAccountName(itemJsInfo.getAccountName());
            transferOrder.setOriginAccountNo(transferSubject.getAccount());
            transferOrder.setOriginAccountName(transferSubject.getAccountName());
            Long transAmount = AmountUtil.convertDollar2CentLong(item.getTransAmount());
            transferOrder.setIfCode(CS.IF_CODE.ALIAQF);
            transferOrder.setAmount(transAmount);
            transferOrder.setRealAmount(transAmount);
            transferOrder.setEntryType(itemJsInfo.getEntryType());
            Map<String, PaywayFee> paywayFeeMap = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByMchApp(transferSubject.getMchNo()), CS.SYS_ROLE_TYPE.MCH, transferSubject.getTransIfCode(), null, null, transferSubject.getIsvNo(), true);
            if(paywayFeeMap == null){
                throw new BizException("转账费率信息异常");
            }
            PaywayFee paywayFee = paywayFeeMap.get(transferOrder.getEntryType());
            if(paywayFee == null){
                throw new BizException("未获取到指定的打款方式的费率信息");
            }
            MutablePair<String, Long> feeAndSnapshot = paywayFee.calFeeAndSnapshot(transAmount);
            Long fee = feeAndSnapshot.right == 0L ? BigDecimal.ONE.longValue() : feeAndSnapshot.right;
            transferOrder.setFeeCostType(TransferOrder.COST_TYPE_ACCOUNT);
            transferOrder.setMchFeeRate(feeAndSnapshot.left);
            transferOrder.setMchOrderFeeAmount(fee);
            transferOrder.setTransferDesc(item.getTransferDesc());
            if (StringUtils.isNotEmpty(item.getBatchId())) {
                transferOrder.setBatchId(item.getBatchId());
            }
            transferOrder.setTransferType(TransferOrderEntity.TRANSFER_TYPE_DF);

            dataList.add(transferOrder);
        }

        //先进行手续费账户余额校验
        long total = 0;
        for (TransferOrder transferOrder : dataList) {
            total  = ObjUtil.defaultIfNull(total + transferOrder.getMchOrderFeeAmount(), 0L );
        }

        String infoId;
        if (CS.SYS_ROLE_TYPE.AGENT.equals(transferSubject.getInfoType())) {
            infoId = transferSubject.getAgentNo();
        } else {
            infoId = transferSubject.getMchNo();
        }

        accountInfoService.checkBalance(infoId, AccountInfo.Type.SERVICE_CHARGE, total);

        transferOrderService.saveBatch(dataList);

        return resut;
    }

    public CertAlipayRequest getCertAliPayRequest(String isvNo) {
        TransferInterfaceConfigEntity transferInterfaceConfigEntity = transferInterfaceConfigService.getTransferConfig(CS.IF_CODE.ALIAQF, isvNo, CS.SYS_ROLE_TYPE.ISV);
        Assert.notNull(transferInterfaceConfigEntity, "所选渠道配置不存在");

        CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
        ChannelCertConfigKitBean channelCertConfigKitBean = SpringBeansUtil.getBean(ChannelCertConfigKitBean.class);
        AliaqfIsvParams isvParams = JSONObject.parseObject(transferInterfaceConfigEntity.getTransIfParams(), AliaqfIsvParams.class);
        // 支付宝网关
        certAlipayRequest.setServerUrl(AlipayConfig.PROD_SERVER_URL);
        certAlipayRequest.setAppId(isvParams.getAppId());
        certAlipayRequest.setPrivateKey(isvParams.getPrivateKey());
        certAlipayRequest.setCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAppPublicCert()));
        certAlipayRequest.setAlipayPublicCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAlipayPublicCert()));
        certAlipayRequest.setRootCertPath(channelCertConfigKitBean.getCertFilePath(isvParams.getAlipayRootCert()));
        certAlipayRequest.setSignType("RSA2");
        certAlipayRequest.setFormat("json");
        certAlipayRequest.setCharset("UTF-8");

        return certAlipayRequest;
    }

    /**
     * 根据付款人信息id获取详情
     */
    public TransferSubjectEntity getSubjectOne(String subId){
        TransferSubjectEntity transferSubjectEntity = transferSubjectService.getById(subId);
        if (transferSubjectEntity != null){
            return transferSubjectEntity;
        }else {
            throw new BizException("未查询到当前付款人信息！");
        }
    }
}
