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.PayOrder;
import com.jeequan.jeepay.core.entity.RefundOrder;
import com.jeequan.jeepay.core.exception.ResponseException;
import com.jeequan.jeepay.core.model.autopos.ChannelOrderAcceptParams;
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.AbstractPosNoticeService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

/**
 * 富友智能POS回调
 *
 * @author zx
 *
 * @date 2021-06-07 07:15
 */
@Service
@Slf4j
public class DgpayPosNoticeService extends AbstractPosNoticeService {

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

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

        JSONObject params = getReqParamJSON();

        String respCode = params.getString("resp_code");
        if (!StringUtils.equals(DgPayKit.STATE_SUCCESS, respCode)) {
            log.info("汇付斗拱智能POS【订单推送模式】回调处理失败，resp_code={}", respCode);
            throw ResponseException.buildText("ERROR");
        }

        // 交易数据
        JSONObject respData = params.getJSONObject("resp_data");
        String subRespCode = respData.getString("sub_resp_code");
        if (!StringUtils.equals(DgPayKit.STATE_SUCCESS, subRespCode)) {
            log.info("汇付斗拱智能POS【订单推送模式】回调处理失败，sub_resp_code={}", subRespCode);
            throw ResponseException.buildText("ERROR");
        }

        String payOrderId = respData.getString("mer_ord_id");
        String transType = respData.getString("trans_type"); // TRANS_REFUND: 交易退款      SCAN_REFUND: 终端扫码退款

        String tradeType = "";
        if (StringUtils.isNotBlank(transType)) {
            tradeType = ChannelOrderAcceptParams.TRADE_TYPE_PAYMENT;

            if (StringUtils.equalsAny(transType, "TRANS_REFUND", "SCAN_REFUND")) {
                tradeType = ChannelOrderAcceptParams.TRADE_TYPE_REFUND;
            }
        }

        log.info("斗拱智能POS【订单推送模式】通知参数：tradeType={}，params={}", tradeType, params.toJSONString());
        return Triple.of(tradeType, payOrderId, params);
    }

    @Override
    public ChannelRetMsg payNotice(HttpServletRequest request, Object params, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) {

        String logPrefix = "处理斗拱智能POS【订单推送模式】支付回调";
        JSONObject jsonParams = (JSONObject) params;

        // 验签
        validate(jsonParams, mchAppConfigContext, payOrder.getIfCode(), logPrefix);

        // 获取请求参数
        JSONObject respData = jsonParams.getJSONObject("resp_data");

        String transAmt = AmountUtil.convertDollar2Cent(respData.getString("trans_amt"));
        if (!String.valueOf(payOrder.getAmount()).equals(transAmt)) {
            log.error("{} 金额不符，trans_amt={}，amount={}", logPrefix, transAmt, payOrder.getAmount());
            throw ResponseException.buildText("ERROR");
        }

        // 判断上游订单状态
        ResponseEntity okResponse = textResp("RECV_ORD_ID_" + payOrder.getPayOrderId());

        ChannelRetMsg result = new ChannelRetMsg();
        // 默认支付中
        result.setChannelState(ChannelRetMsg.ChannelState.WAITING);

        String transStat = respData.getString("trans_stat"); // 支付状态  I：初始、P：处理中、S：成功、F：失败
        if(DgPayKit.STATE_SUCCESS_S.equals(transStat)){
            result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);

        }else if(DgPayKit.STATE_FAIL_F.equals(transStat)){
            result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
        }

        result.setResponseEntity(okResponse);
        result.setChannelOrderId(respData.getString("req_seq_id"));
        return result;
    }

    @Override
    public ChannelRetMsg refundNotice(HttpServletRequest request, Object params, RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) {
        String logPrefix = "处理斗拱智能POS【订单推送模式】退款通知";

        JSONObject jsonParams = (JSONObject) params;

        // 验签
        validate(jsonParams, mchAppConfigContext, refundOrder.getIfCode(), logPrefix);

        // 获取请求参数
        JSONObject respData = jsonParams.getJSONObject("resp_data");
        String transAmt = AmountUtil.convertDollar2Cent(respData.getString("ord_amt"));
        if (!String.valueOf(refundOrder.getRefundAmount()).equals(transAmt)) {
            log.error("{} 金额不符，ord_amt={}，amount={}", logPrefix, transAmt, refundOrder.getRefundAmount());
            throw ResponseException.buildText("ERROR");
        }

        // 判断上游订单状态
        ResponseEntity okResponse = textResp("RECV_ORD_ID_" + refundOrder.getRefundOrderId());

        ChannelRetMsg result = new ChannelRetMsg();
        // 默认支付中
        result.setChannelState(ChannelRetMsg.ChannelState.WAITING);

        String transStat = respData.getString("trans_stat"); // 支付状态  I：初始、P：处理中、S：成功、F：失败
        if(DgPayKit.STATE_SUCCESS_S.equals(transStat)){
            result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);

        }else if(DgPayKit.STATE_FAIL_F.equals(transStat)){
            result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
        }

        result.setResponseEntity(okResponse);
        result.setChannelOrderId(respData.getString("hf_seq_id"));
        return result;
    }

    /**
     * 验签
     * @return
     */
    private void validate(JSONObject jsonParams, MchAppConfigContext mchAppConfigContext, String ifCode, String logPrefix) {

        String sign = jsonParams.getString("sign");

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

        // 验证签名
        boolean verifyResult = DgPayKit.verify(jsonParams.getString("resp_data"), isvParams.getPosPublicKey(), sign);
        // 验签失败
        if(!verifyResult){
            log.error("{} 验签失败", logPrefix);
            throw ResponseException.buildText("SIGN ERROR");
        }

    }

}
