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

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
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.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.yspay.YspayIsvParams;
import com.jeequan.jeepay.core.model.params.yspay.YspayIsvsubMchParams;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRefundLimit;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.model.rqrs.refund.RefundOrderRQ;
import com.jeequan.jeepay.core.utils.AmountUtil;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.thirdparty.channel.AbstractRefundService;
import com.jeequan.jeepay.thirdparty.channel.yspay.utils.YspayKit;
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
import org.springframework.stereotype.Service;

/**
 * 退款接口： 银盛支付
 *
 * @author xiaoyu
 *
 * @date 2022/4/15 9:34
 */
@Service
public class YspayRefundService extends AbstractRefundService {

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

    @Override
    public String preCheck(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder) {
        ChannelRefundLimit refundLimit = this.isRefundLimit(payOrder.getSettleType(),payOrder.getMchExtNo());
        if(refundLimit.getIsPlatAccount()){
            this.checkPlatAccount(refundOrder);
        }
        return null;
    }

    @Override
    public ChannelRetMsg refund(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) throws Exception {


        ChannelRetMsg channelRetMsg = new ChannelRetMsg();
        JSONObject bizContent = new JSONObject();
        JSONObject response = null;
        String code = null;
        YspayIsvsubMchParams mchParams = (YspayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getAppId(), payOrder.getIfCode());
        // 如果为分账模式下单。走分账退款
        if (mchParams.getPayType() != null && mchParams.getPayType().equals(YspayIsvsubMchParams.PAY_TYPE_DIVISION)) {
            // 商户原交易订单号
            bizContent.put("out_trade_no", payOrder.getPayOrderId());
            // 商户系统的交易发生日期格式yyyyMMdd 示例值：20180525
            bizContent.put("shopdate", DateUtil.format(payOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
            // 银盛原交易流水号
            bizContent.put("trade_no", payOrder.getChannelOrderNo());
            // 需要退款的金额，该金额不能大于订单金额,单位为元，支持两位小数，Number(10,2)指10位长度，2位精度
            bizContent.put("refund_amount", AmountUtil.convertCent2Dollar(refundOrder.getRefundAmount()+""));
            // 退款的原因说明，该参数最长为50个汉字。
            bizContent.put("refund_reason", "分账退款");
            // 标商户系统生成的退款订单号，标识一次退款请求，同一笔交易多次退款需要保证唯一。
            bizContent.put("out_request_no", refundOrder.getRefundOrderId());
            // 原交易是否参与分账（01或空代表是，02代表否）
            bizContent.put("is_division", "02");
            // 原交易分账模式（01：比例，02：金额）
            bizContent.put("ori_division_mode", "02");

            String result = YspayKit.divisionRequest(YspayKit.DIVISION_REFUND_URL, "ysepay.online.trade.refund.split", mchAppConfigContext.getMchApplyment().getIsvNo(), bizContent, null, payOrder.getIfCode());
            JSONObject resJson = JSONObject.parseObject(result);
            response = resJson.getJSONObject("ysepay_online_trade_refund_split_response");
            code = response.getString("code");
        }else {
            String method = "ysepay.online.trade.refund";
            // 配置参数
            ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
            YspayIsvParams isvParams = (YspayIsvParams) configContextQueryService.queryIsvParams(mchAppConfigContext.getMchApplyment());
            if(RefundOrder.REFUND_ACCOUNT_PLAT.equals(refundOrder.getExtParam())){
                //一般户退款
                method = "ysepay.online.trade.refund.general.account";
                bizContent.put("refund_mer_id",isvParams.getPartnerId());
            }
            // 商户订单号
            bizContent.put("out_trade_no", payOrder.getPayOrderId());
            // 订单交易日期
            bizContent.put("shopdate", DateUtil.format(payOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
            // 退款金额
            bizContent.put("refund_amount", AmountUtil.convertCent2Dollar(refundOrder.getRefundAmount()));
            // 退款备注
            bizContent.put("refund_reason", refundOrder.getRefundReason());
            // 退款订单号
            bizContent.put("out_request_no", refundOrder.getRefundOrderId());
            String result = YspayKit.payRequest(method, mchAppConfigContext, bizContent, getNotifyUrl(), payOrder.getIfCode());
            JSONObject resJson = JSONObject.parseObject(result);
            response = resJson.getJSONObject(method.replace(".","_") + "_response");
            code = response.getString("code");
        }

        if (YspayKit.RES_CODE.equals(code)) {
            String transNo = response.getString("refundsn");
            channelRetMsg.setChannelOrderId(transNo);
            channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
        } else {  //其他状态, 表示支付中
            channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
        }
        return channelRetMsg;
    }

    @Override
    public ChannelRetMsg query(RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) throws Exception {

        YspayIsvsubMchParams mchParams = (YspayIsvsubMchParams) configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getMchApplyment().getAutoConfigMchAppId(), refundOrder.getIfCode());
        ChannelRetMsg channelRetMsg = new ChannelRetMsg();
        channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING); //认为是处理中

        JSONObject bizContent = new JSONObject();

        // 商户订单号
        bizContent.put("out_trade_no", refundOrder.getPayOrderId());
        // 退款订单号
        bizContent.put("out_request_no", refundOrder.getRefundOrderId());

        String result = null;
        // 如果为分账模式下单。走分账退款
        if (mchParams.getPayType() != null && mchParams.getPayType().equals(YspayIsvsubMchParams.PAY_TYPE_DIVISION)) {
            result = YspayKit.payRequest(YspayKit.DIVISION_REFUND_URL,"ysepay.online.trade.refund.query", mchAppConfigContext, bizContent, getNotifyUrl(), refundOrder.getIfCode());
        }else {
            result = YspayKit.payRequest("ysepay.online.trade.refund.query", mchAppConfigContext, bizContent, getNotifyUrl(), refundOrder.getIfCode());
        }
        JSONObject resJson = JSONObject.parseObject(result);
        JSONObject response = resJson.getJSONObject("ysepay_online_trade_refund_query_response");
        String code = response.getString("code");
        if (YspayKit.RES_CODE.equals(code)) {
            String tradeStatus = response.getString("refund_state");
            if("success".equals(tradeStatus)){ // 退款成功
                String transNo = response.getString("refundsn");
                channelRetMsg.setChannelOrderId(transNo);
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);

            }else if ("fail".equals(tradeStatus)) {
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
                channelRetMsg.setChannelErrCode(response.getString("code"));
                channelRetMsg.setChannelErrMsg(response.getString("sub_msg"));
            }else {  //其他状态, 表示支付中
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
            }
        }else {
            channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
            channelRetMsg.setChannelErrCode(response.getString("code"));
            channelRetMsg.setChannelErrMsg(response.getString("sub_msg"));
        }
        return channelRetMsg;
    }

    /**
     * 银盛支持
     * @return
     */
    @Override
    public ChannelRefundLimit isRefundLimit(String settleType,String applyId) {
        ChannelRefundLimit channelRefundLimit = new ChannelRefundLimit(true,true);
        if(CS.SETTLEMENT_TYPE.D0.equals(settleType)){
            channelRefundLimit.setIsDefaultAccount(false);
        }
        return channelRefundLimit;
    }

    @Override
    public void checkPlatAccount(RefundOrder refundOrder) {
        super.checkPlatAccount(refundOrder);
    }
}
