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

import cn.hutool.core.lang.Assert;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayFundTransCommonQueryModel;
import com.alipay.api.domain.AlipayFundTransUniTransferModel;
import com.alipay.api.domain.BankcardExtInfo;
import com.alipay.api.domain.Participant;
import com.alipay.api.request.AlipayFundTransCommonQueryRequest;
import com.alipay.api.request.AlipayFundTransUniTransferRequest;
import com.alipay.api.response.AlipayFundAccountbookQueryResponse;
import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
import com.alipay.api.response.AlipayFundTransUniTransferResponse;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.AccountOperate;
import com.jeequan.jeepay.core.entity.TransferOrder;
import com.jeequan.jeepay.core.entity.TransferWallet;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
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.model.rqrs.transfer.TransferOrderRQ;
import com.jeequan.jeepay.core.model.tranfer.TransferBasicInfo;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.service.impl.AccountInfoService;
import com.jeequan.jeepay.service.impl.TransferInterfaceConfigService;
import com.jeequan.jeepay.service.impl.TransferSubjectService;
import com.jeequan.jeepay.thirdparty.channel.AbstractTransferService;
import com.jeequan.jeepay.thirdparty.channel.alipay.AliAqfV2Service;
import com.jeequan.jeepay.thirdparty.util.ChannelCertConfigKitBean;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

/**
 * TODO
 *
 * @author deng
 * @since 2024/5/11
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AliaqfTransferService extends AbstractTransferService {
    private final AccountInfoService accountInfoService;
    private final TransferSubjectService transferSubjectService;
    private final TransferInterfaceConfigService interfaceConfigService;
    private final AliAqfV2Service aliAqfV2Service;

    @Override
    public String getIfCode() {
        return CS.IF_CODE.ALIAQF;
    }

    @Override
    public boolean isSupport(String entryType) {
        return TransferBasicInfo.ENTRY_TYPE_BANK.equals(entryType) || TransferBasicInfo.ENTRY_TYPE_ZFB.equals(entryType);
    }

    public void rollBackServiceCharge(TransferOrder transferOrder) {
        // 预扣手续费回退
        TransferSubjectEntity transferSubject = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
        String infoId;
        if (transferSubject.getInfoType().equals(CS.SYS_ROLE_TYPE.MCH)) {
            infoId = transferSubject.getMchNo();
        } else {
            infoId = transferSubject.getAgentNo();
        }
        AccountInfo accountInfo = accountInfoService.getAccountInfo(infoId, AccountInfo.Type.SERVICE_CHARGE.getType());

        // 预扣手续费
        AccountOperate accountOperate = new AccountOperate(accountInfo.getAccountNo(), transferOrder.getAmount(),
                AccountFundInfo.ChangeType.TRANSFER.getValue(), AccountFundInfo.ChangeMethod.DF.getValue(),
                transferOrder.getTransferId(), "代付失败手续费回退");
        accountOperate.setFinalAmt(-transferOrder.getMchOrderFeeAmount());
        accountOperate.setIsUpdateAccount(true);
        accountInfoService.upAccount(accountOperate);

    }

    @Override
    public ChannelRetMsg transfer(TransferOrderRQ bizRQ, TransferOrder transferOrder) throws Exception {
        log.info("进入了支付宝直付通代发！");
        ChannelRetMsg retMsg = ChannelRetMsg.waiting();

        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(transferOrder.getIsvNo());
        TransferSubjectEntity ersubjectEntity = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
        TransferSubjectEntity eesubjectEntity = transferSubjectService.getById(transferOrder.getTransferSubjectIdJs());
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
            AlipayFundTransUniTransferModel model = new AlipayFundTransUniTransferModel();

            model.setOutBizNo(transferOrder.getTransferId());
            model.setTransAmount(AmountUtil.convertCent2Dollar(transferOrder.getAmount()));
            model.setProductCode("SINGLE_TRANSFER_NO_PWD");
            model.setBizScene("ENTRUST_TRANSFER");
            model.setOrderTitle(StringUtils.isNotEmpty(transferOrder.getTransferDesc()) ? transferOrder.getTransferDesc() : "支付宝代发到户！");
            //付款方信息
            Participant participanter = new Participant();
            participanter.setIdentity(ersubjectEntity.getTransChannelMchNo());
            participanter.setIdentityType("ACCOUNT_BOOK_ID");
            JSONObject erparm = new JSONObject();
            erparm.put("agreement_no", ersubjectEntity.getTransChannelSignNo());
            participanter.setExtInfo(erparm.toJSONString());
            model.setPayerInfo(participanter);
            //收款方信息
            Participant participantee = new Participant();
            participantee.setIdentity(eesubjectEntity.getAccount());
            if (TransferOrderEntity.ENTRY_ALIPAY_CASH.equals(transferOrder.getEntryType())){
                participantee.setIdentityType("ALIPAY_LOGON_ID");
                participantee.setName(eesubjectEntity.getAccountName());
            }else if (TransferOrderEntity.ENTRY_BANK_CARD.equals(transferOrder.getEntryType())){
                participantee.setIdentityType("BANKCARD_ACCOUNT");
                BankcardExtInfo bankcardExtInfo = new BankcardExtInfo();
                participantee.setName(eesubjectEntity.getAccountName());
                if (eesubjectEntity.getAccountType() == TransferBasicInfo.ACCOUNT_TYPE_COR) {
                    //对公
                    String accountMessage = eesubjectEntity.getAccountMessage();
                    if (StringUtils.isNotEmpty(accountMessage)) {
                        JSONObject jsonObject = JSONObject.parseObject(accountMessage);
                        bankcardExtInfo.setAccountType("1");
                        bankcardExtInfo.setInstName(jsonObject.getString("instName"));
                        bankcardExtInfo.setInstProvince(jsonObject.getString("instProvince"));
                        bankcardExtInfo.setInstCity(jsonObject.getString("instCity"));
                        bankcardExtInfo.setInstBranchName(jsonObject.getString("instBranchName"));
                        participantee.setBankcardExtInfo(bankcardExtInfo);
                        transferOrder.setBankName(jsonObject.getString("instName"));
                    }
                } else {
                    //对私
                    bankcardExtInfo.setAccountType("2");
                    participantee.setBankcardExtInfo(bankcardExtInfo);
                }
            }
            model.setPayeeInfo(participantee);
            request.setBizModel(model);
            AlipayFundTransUniTransferResponse response = alipayClient.certificateExecute(request);
            retMsg.setChannelAttach(response.getBody());
            if (response.isSuccess()) {
                retMsg.setChannelOrderId(response.getOrderId());
                retMsg.setPlatformOrderNo(response.getPayFundOrderId());
            } else {
                retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
                retMsg.setChannelErrMsg(response.getSubMsg());
                retMsg.setChannelErrCode(response.getSubCode());
            }
        } catch (Exception e) {
            log.info("代发异常！",e);
            retMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
            retMsg.setChannelErrMsg(e.getMessage());

            rollBackServiceCharge(transferOrder);
        }
        return retMsg;
    }

    @Override
    public ChannelRetMsg query(TransferOrder transferOrder, MchAppConfigContext mchAppConfigContext) {
        log.info("进入了支付宝账单查询");

        TransferSubjectEntity transferSubjectFq = transferSubjectService.getById(transferOrder.getTransferSubjectIdFq());
        CertAlipayRequest certAlipayRequest = getCertAliPayRequest(transferSubjectFq.getIsvNo());
        AlipayFundTransCommonQueryResponse response;
        if ( transferSubjectFq.getTransChannelSignNo() == null || transferSubjectFq.getTransChannelMchNo() == null) {
            throw new BizException("当前付款人签约或开通记账本！");
        }

        ChannelRetMsg channelRetMsg = new ChannelRetMsg();
        channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.UNKNOWN);
        try {
            AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
            AlipayFundTransCommonQueryRequest request = new AlipayFundTransCommonQueryRequest();
            AlipayFundTransCommonQueryModel model = new AlipayFundTransCommonQueryModel();
            model.setProductCode(TransferOrder.ENTRY_BANK_CARD.equals(transferOrder.getEntryType()) ? "TRANS_BANKCARD_NO_PWD" : "TRANS_ACCOUNT_NO_PWD");
            model.setBizScene("DIRECT_TRANSFER");
            model.setOutBizNo(transferOrder.getTransferId());
            request.setBizModel(model);

            channelRetMsg.setChannelOrderId(transferOrder.getChannelOrderNo());
            response = alipayClient.certificateExecute(request);
            channelRetMsg.setChannelOriginResponse(response.getBody());
            channelRetMsg.setResponseEntity(ResponseEntity.ok("SUCCESS"));

            if (response.isSuccess()) {
                log.info("安全发账单查询成功：" + response.getBody());
            } else {
                log.error("安全发账单查询失败！" + response.getSubMsg());
                return channelRetMsg;
            }

            String status = response.getStatus();
            if (AliaqfKit.ORDER_SUCCESS.equals(status)) {
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
                channelRetMsg.setChannelOrderId(response.getOrderId());
                channelRetMsg.setPlatformOrderNo(response.getPayFundOrderId());
            } else if (AliaqfKit.ORDER_FAIL.equals(status)) {
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
                rollBackServiceCharge(transferOrder);
            } else if (AliaqfKit.ORDER_DEALING.equals(status)) {
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
            }

            return channelRetMsg;
        } catch (Exception e) {
            log.info("支付宝安全发查询订单状态异常, {}", transferOrder.getTransferId(), e);
        }

        return channelRetMsg;
    }

    @Override
    public MutablePair<String, Long> queryBalanceAmount(TransferWallet transferWallet) {
        AlipayFundAccountbookQueryResponse queryResultData = aliAqfV2Service.fundAccountbookQuery(transferWallet.getTransApplyId(), transferWallet.getWalletApplyId());

        String availableAmount = queryResultData.getAvailableAmount();

        return new MutablePair<>(transferWallet.getTransApplyId(), AmountUtil.convertDollar2CentLong(availableAmount));

    }

    public CertAlipayRequest getCertAliPayRequest(String isvNo) {
        TransferInterfaceConfigEntity transferInterfaceConfigEntity = interfaceConfigService.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;
    }
}
