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

import com.alibaba.fastjson.JSONObject;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.exception.ResponseException;
import com.jeequan.jeepay.core.model.autopos.ChannelOrderAcceptParams;
import com.jeequan.jeepay.core.model.autopos.ChannelOrderAcceptRetMsg;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.IsvParams;
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.core.utils.JsonKit;
import com.jeequan.jeepay.thirdparty.channel.AbstractChannelOrderAcceptService;
import com.jeequan.jeepay.thirdparty.channel.dgpay.utils.MD5Utils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;

/**
 * 斗拱智能POS回调
 *
 * @author zx
 *
 * @date 2021-06-07 07:15
 */
@Service
@Slf4j
public class DgpayChannelOrderAcceptService extends AbstractChannelOrderAcceptService {

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

    @Override
    public ChannelOrderAcceptParams parseParams(HttpServletRequest request, IsvParams isvParams) {

        JSONObject params = getReqParamJSON();

        // 获取事件类型
        String eventDefineNo = params.getString("event_define_no");

        String tradeType = ""; // 交易类型  收款-PAYMENT  退款-REFUND
        if (DgPayKit.POS_PAY_EVENT.contains(eventDefineNo)) {
            tradeType = ChannelOrderAcceptParams.TRADE_TYPE_PAYMENT;
        } else if (DgPayKit.POS_REFUND_EVENT.contains(eventDefineNo)) {
            tradeType = ChannelOrderAcceptParams.TRADE_TYPE_REFUND;
        }

        log.info("斗拱智能POS【订单通知模式】通知参数：tradeType={}，params={}", tradeType, params.toJSONString());
        return ChannelOrderAcceptParams.buildAutoPosParams(tradeType, params.getString("devs_id"), params);
    }

    @Override
    public ChannelOrderAcceptRetMsg payNotice(HttpServletRequest request, Object params, MchAppConfigContext mchAppConfigContext, String ifCode) throws Exception {

        String logPrefix = "处理斗拱智能POS【订单通知模式】支付通知";

        ChannelOrderAcceptRetMsg result = new ChannelOrderAcceptRetMsg();
        result.setChannelState(ChannelRetMsg.ChannelState.WAITING);

        // 获取请求参数
        JSONObject jsonParams = (JSONObject) params;

        // 验签
        boolean verifyResult = validateSign(jsonParams, mchAppConfigContext, request.getParameterMap().get("sign")[0], ifCode);
        if(!verifyResult){
            log.info("{}验证通知数据及签名失败", logPrefix);
            throw ResponseException.buildText4HttpStatus500("FAIL");
        }

        // 支付状态
        String status = jsonParams.getString("trans_stat");
        // 支付成功
        if (StringUtils.equals(DgPayKit.STATE_SUCCESS_S, status)) {
            result.setResponseEntity(textResp("SUCCESS")); // 通知上游处理成功
            result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);

            JSONObject transOrderInfo = jsonParams.getJSONObject("trans_order_info");
            result.setChannelOrderId(transOrderInfo.getString("mer_ord_id")); // 渠道订单号，必填
            result.setChannelBizData(JsonKit.newJson("reqSeqId", transOrderInfo.getString("req_seq_id"))); // 分账使用 渠道特殊参数

            result.setChannelAmount(AmountUtil.convertDollar2CentLong(jsonParams.getString("trans_amt")));  // 订单金额，单位分，必填
            result.setBizOrderId(transOrderInfo.getString("mer_ord_id"));
            result.setChannelWayCode(CS.PAY_WAY_CODE.AUTO_POS); // 支付方式，必填
            result.setChannelWayCodeType(covertWayCodeType(jsonParams.getString("event_define_no"))); // 支付方式类型，必填
            result.setChannelDivisionMode(jsonParams.getByte("is_delay_acct"));

        }
        return result;
    }


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

            ChannelOrderAcceptRetMsg result = new ChannelOrderAcceptRetMsg();
            result.setChannelState(ChannelRetMsg.ChannelState.WAITING);

            // 获取请求参数
            JSONObject jsonParams = (JSONObject) params;

            // 验签
            boolean verifyResult = validateSign(jsonParams, mchAppConfigContext, request.getParameterMap().get("sign")[0], ifCode);
            if(!verifyResult){
                log.info("{}验证通知数据及签名失败", logPrefix);
                throw ResponseException.buildText4HttpStatus500("FAIL");
            }

            // 退款状态
            String status = jsonParams.getString("trans_stat");
            // 退款成功
            if (StringUtils.equals(DgPayKit.STATE_SUCCESS_S, status)) {
                result.setResponseEntity(textResp("SUCCESS")); // 通知上游处理成功
                result.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
                result.setChannelOrderId(jsonParams.getString("mer_ord_id")); // 渠道订单号，必填

                result.setChannelAmount(AmountUtil.convertDollar2CentLong(jsonParams.getString("ord_amt")));  // 订单金额，单位分，必填
                result.setBizOrderId(jsonParams.getString("mer_ord_id"));
                result.setChannelPayOrderId(jsonParams.getString("org_term_ord_id"));  // 原渠道订单号（和支付订单渠道订单号一致），退款必填
                result.setChannelDivisionRefundMode((byte) 1);
            }
            return result;

        } catch (Exception e) {
            log.error("error", e);
            throw ResponseException.buildText4HttpStatus500("FAIL");
        }
    }

    /**
     * 验签
     * @return
     */
    public boolean validateSign(JSONObject jsonParams, MchAppConfigContext mchAppConfigContext, String sign, String ifCode) throws Exception {

        DgpayIsvParams isvParams =
                (DgpayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment().getIsvNo(), ifCode);

        return MD5Utils.verifySign(jsonParams.toJSONString(), isvParams.getWebhookPrivateKey(), sign);
    }

    private String covertWayCodeType(String eventDefineNo) {

        switch (eventDefineNo) {
            case "pay.ali_scaned": return CS.PAY_WAY_CODE_TYPE.ALIPAY;
            case "pay.wx_scaned": return CS.PAY_WAY_CODE_TYPE.WECHAT;
            case "pay.union_scaned":
            case "pay.card_consume.pos":
            case "pay.digit_scaned":
                return CS.PAY_WAY_CODE_TYPE.UNIONPAY;
            default: return CS.PAY_WAY_CODE_TYPE.OTHER;
        }
    }

}
