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

import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.entity.ChannelAccountCashoutRecord;
import com.jeequan.jeepay.core.exception.ResponseException;
import com.jeequan.jeepay.core.model.cashout.CashoutRetMsg;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvParams;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelCashoutNoticeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

/**
 * 斗拱提现回调
 *
 * @author zx
 *
 * @date 2023-06-14 07:15
 */
@Service
@Slf4j
public class DgpayChannelCashoutNoticeService extends AbstractChannelCashoutNoticeService {

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

    @Override
    public MutablePair<String, Object> parseParams(HttpServletRequest request, String urlRid) {

        try {

            // 回调参数body【回调参数顺序固定】
            JSONObject reqParamJSON = getReqParamJSON();
            log.info("【斗拱提现回调参数】{}", reqParamJSON);
            JSONObject respData = reqParamJSON.getJSONObject("resp_data");
            String rid = respData.getString("req_seq_id");
            log.info("【斗拱提现回调参数】{}", respData);
            return MutablePair.of(rid, reqParamJSON);

        } catch (Exception e) {
            log.error("error", e);
            throw ResponseException.buildText("ERROR");
        }
    }

    @Override
    public CashoutRetMsg doNotice(HttpServletRequest request, Object params, ChannelAccountCashoutRecord cashoutRecord, MchAppConfigContext mchAppConfigContext) {
        try {
            String logPrefix = "处理斗拱提现回调";

            CashoutRetMsg cashoutRetMsg = new CashoutRetMsg();

            JSONObject jsonParams = (JSONObject) params;
            log.info("{}参数：{}", logPrefix, jsonParams);

            // 业务失败
            if (!"10000".equals(jsonParams.getString("resp_code"))) {
                log.error("{} 业务失败，原因：{}", logPrefix, jsonParams.getString("resp_desc"));
                throw ResponseException.buildText("ERROR");
            }

            String respDataStr = jsonParams.getString("resp_data");
            JSONObject respDataJSON = JSONObject.parseObject(respDataStr);
            String sign = jsonParams.getString("sign");

            // 交易状态  S：成功    F：失败    P：处理中
            String transStat = respDataJSON.getString("trans_status");
            if (DgPayKit.STATE_SUCCESS_S.equals(transStat)) {
                cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
                cashoutRetMsg.setChannelOrderId(respDataJSON.getString("hf_seq_id")); // 渠道提现单号

            }else if (DgPayKit.STATE_FAIL_F.equals(transStat)) {
                cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
                cashoutRetMsg.setChannelErrCode(respDataJSON.getString("sub_resp_code"));
                cashoutRetMsg.setChannelErrMsg(respDataJSON.getString("sub_resp_desc"));

            }else {
                cashoutRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);

            }

            // 返回上游内容
            cashoutRetMsg.setResponseEntity(textResp("SUCCESS"));

            // 校验提现回调
            boolean verifyResult = verifyParams(respDataStr, cashoutRecord, mchAppConfigContext, sign);
            // 验证参数失败
            if(!verifyResult){
                log.info("{}验证提现通知数据或签名失败", logPrefix);
                throw ResponseException.buildText("ERROR");
            }

            cashoutRetMsg.setChannelOrderId(jsonParams.getString("acquireOrderNo"));
            cashoutRetMsg.setBankName(jsonParams.getString("bankName"));
            cashoutRetMsg.setBankAccount(jsonParams.getString("bankAccount"));
            cashoutRetMsg.setBankAccountName(jsonParams.getString("bankAccountName"));

            return cashoutRetMsg;

        } catch (Exception e) {
            log.error("error", e);
            throw ResponseException.buildText("ERROR");
        }
    }

    /**
     * 验证斗拱提现通知参数
     * @return
     */
    public boolean verifyParams(String respDataStr, ChannelAccountCashoutRecord cashoutRecord, MchAppConfigContext mchAppConfigContext, String sign) {
        // 提现金额
        String txnAmt = JSONObject.parseObject(respDataStr).getString("cash_amt");
        if (StringUtils.isEmpty(txnAmt)) {
            log.info("金额参数为空 [txnAmt] :{}", txnAmt);
            return false;
        }
        // 核对金额
        long dbPayAmt = cashoutRecord.getCashoutAmount();
        if (dbPayAmt != AmountUtil.convertDollar2CentLong(txnAmt)) {
            log.info("订单金额与参数金额不符。 dbPayAmt={}, txnAmt={}, rid={}", dbPayAmt, txnAmt, cashoutRecord.getRid());
            return false;
        }

        // 公钥参数
        DgpayIsvParams isvParams = (DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), cashoutRecord.getIfCode());

        // 验证签名
        boolean verifyResult = DgPayKit.verify(respDataStr, isvParams.getRsaPublicKey(), sign);
        if(!verifyResult){
            log.info("【斗拱提现回调】 验签失败！ 回调参数：respDataStr = {}", respDataStr);
            return false;
        }

        return true;
    }

}
