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

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.exception.BizException;
import com.jeequan.jeepay.core.exception.ChannelException;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.params.dgpay.DgpayIsvsubMchParams;
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.service.ConfigContextQueryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

/**
 * 退款接口： 斗拱
 *
 * @author xiaoyu
 *
 * @date 2022/6/9 17:43
 */
@Slf4j
@Service
public class DgpayRefundService extends AbstractRefundService {

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

    @Override
    public String preCheck(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder) {
        return null;
    }

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

        // 智能pos收款，走独立退款接口
        if (StringUtils.equals(payOrder.getWayCode(), CS.PAY_WAY_CODE.AUTO_POS)) {
            return autoPosRefund(bizRQ, refundOrder, payOrder, mchAppConfigContext);
        }

        ChannelRetMsg channelRetMsg = new ChannelRetMsg();
        JSONObject reqParams = new JSONObject();
        // 交易流水号
        reqParams.put("req_seq_id", refundOrder.getRefundOrderId());
        // 原交易请求订单号
        reqParams.put("org_req_seq_id", payOrder.getPayOrderId());
        // 商户号
        reqParams.put("huifu_id", payOrder.getChannelMchNo())
        ;
        reqParams.put("notify_url", getNotifyUrl());
        // 请求日期
        reqParams.put("req_date", DateUtil.format(refundOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
        // 退款金额
        reqParams.put("ord_amt", AmountUtil.convertCent2Dollar(refundOrder.getRefundAmount()));
        // 原交易请求日期
        reqParams.put("org_req_date", DateUtil.format(payOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
        JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/payment/scanpay/refund", refundOrder.getIfCode());
        JSONObject resData = response.getJSONObject("data");
        String code = resData.getString("resp_code");
        // 调用成功
        if(DgPayKit.STATE_SUCCESS.equals(code)){
            String tradeState = resData.getString("trans_stat");
            if (DgPayKit.STATE_SUCCESS_S.equals(tradeState)) {
                String channelOrderNo = resData.getString("hf_seq_id");
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS);
                return ChannelRetMsg.confirmSuccess(channelOrderNo);
            }else if (DgPayKit.STATE_FAIL_F.equals(tradeState)) {
                channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
                // 状态失败
                DgPayKit.channelMsgError(resData, channelRetMsg);
            }
        }else if (DgPayKit.STATE_ING.equals(code)){
            return channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);
        }else{
            channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
            // 状态失败
            DgPayKit.channelMsgError(resData, channelRetMsg);
        }
        return channelRetMsg;
    }

    private ChannelRetMsg autoPosRefund(RefundOrderRQ bizRQ, RefundOrder refundOrder, PayOrder payOrder, MchAppConfigContext mchAppConfigContext) {

        ChannelRetMsg channelRetMsg = new ChannelRetMsg();

        // 智能POS  bizParams参数
        JSONObject bizParams = JSONObject.parseObject(payOrder.getChannelBizData());
        if (bizParams == null || StringUtils.isBlank(bizParams.getString("deviceNo"))) {
            throw new BizException("该订单不支持接口退款，请在POS机完成退款！");
        }

        try {

            // 请求数据data
            JSONObject dataParams = new JSONObject();
            dataParams.put("device_id", bizParams.getString("deviceNo"));

            // 退款信息
            JSONObject jsonData = new JSONObject();
            jsonData.put("interfaceType", "refund");
            jsonData.put("channelId", DgPayKit.covertChannelId(bizParams.getString("channelType"))); // 支付渠道
            jsonData.put("ordAmt", refundOrder.getRefundAmount().toString());
            jsonData.put("oriOutOrderId", payOrder.getPayOrderId()); // 原三方订单号
            jsonData.put("outOrdId", refundOrder.getRefundOrderId()); // 外部订单号
            jsonData.put("bgRetUrl", "virgo://" + getPosNotifyUrl());
            dataParams.put("json_data", jsonData.toJSONString());

            JSONObject response = DgPayKit.request(mchAppConfigContext, dataParams, "/trade/cloudmis/device/information", refundOrder.getIfCode());
            JSONObject resData = response.getJSONObject("data");

            String code = resData.getString("resp_code");
            if(!DgPayKit.STATE_SUCCESS.equals(code)){
                log.error("斗拱智能POS退款失败，错误码：{}，错误信息：{}", code, resData.getString("resp_desc"));
            }

            channelRetMsg.setChannelOrderId(resData.getString("termOrdId"));
            channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);

            return channelRetMsg;

        }catch (BizException e) {
            channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
            channelRetMsg.setChannelErrCode(e.getApiRes().getCode()+"");
            channelRetMsg.setChannelErrMsg(e.getApiRes().getMsg());
        }catch (Exception e) {
            throw ChannelException.sysError(e.getMessage());
        }
        return channelRetMsg;
    }

    @Override
    public ChannelRetMsg query(RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) throws Exception {
        if (StringUtils.equals(refundOrder.getWayCode(), CS.PAY_WAY_CODE.AUTO_POS)) {
            return ChannelRetMsg.waiting();
        }
        try {
            ConfigContextQueryService configContextQueryService = SpringBeansUtil.getBean(ConfigContextQueryService.class);
            DgpayIsvsubMchParams mchParams = (DgpayIsvsubMchParams)configContextQueryService.queryIsvsubMchParams(mchAppConfigContext.getMchNo(), mchAppConfigContext.getMchApplyment().getAutoConfigMchAppId(), refundOrder.getIfCode());
            JSONObject reqParams = new JSONObject();
            // 交易流水号
            reqParams.put("org_req_seq_id", refundOrder.getRefundOrderId());
            // 商户号
            reqParams.put("huifu_id", mchParams.getHuifuId());
            // 原机构请求日期
            reqParams.put("org_req_date", DateUtil.format(refundOrder.getCreatedAt(), DatePattern.PURE_DATE_PATTERN));
            JSONObject response = DgPayKit.request(mchAppConfigContext, reqParams, "/trade/payment/scanpay/refundquery", refundOrder.getIfCode());
            JSONObject resData = response.getJSONObject("data");
            String code = resData.getString("resp_code");
            //如果查询请求成功
            if(DgPayKit.STATE_SUCCESS.equals(code)){
                String tradeState = resData.getString("trans_stat");
                if (DgPayKit.STATE_SUCCESS_S.equals(tradeState)) {
                    return ChannelRetMsg.confirmSuccess(null);
                }else if (DgPayKit.STATE_FAIL_F.equals(tradeState)) {
                    // 失败
                    return ChannelRetMsg.confirmFail();
                }
            }
            //支付中
            return ChannelRetMsg.waiting();
        }catch (Exception e) {
            //支付中
            return ChannelRetMsg.waiting();
        }
    }

    private ChannelRetMsg autoPosQuery(RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext) {

        ChannelRetMsg channelRetMsg = new ChannelRetMsg();

        // 智能POS  bizParams参数
        JSONObject bizParams = JSONObject.parseObject(refundOrder.getChannelBizData());
        if (bizParams == null) {
            throw new BizException("不支持退款补单");
        }

        try {

            // 请求数据data
            JSONObject dataParams = new JSONObject();
            dataParams.put("device_id", bizParams.getString("deviceNo"));

            // 退款信息
            JSONObject jsonData = new JSONObject();
            jsonData.put("interfaceType", "queryOrder");
            jsonData.put("tradeNo", refundOrder.getChannelPayOrderNo()); // 外部订单号
            jsonData.put("outOrdId", refundOrder.getPayOrderId()); // 外部订单号
            jsonData.put("isSale", "0");
            jsonData.put("channelId", DgPayKit.covertChannelId(bizParams.getString("channelType")));
            dataParams.put("json_data ", jsonData.toJSONString());

            JSONObject response = DgPayKit.request(mchAppConfigContext, dataParams, "/trade/cloudmis/device/information", refundOrder.getIfCode());
            JSONObject resData = response.getJSONObject("data");

            String code = resData.getString("resp_code");
            if(!DgPayKit.STATE_SUCCESS.equals(code)){
                log.error("斗拱智能POS退款查单失败，错误码：{}，错误信息：{}", code, resData.getString("resp_desc"));
            }

            return channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.WAITING);

        }catch (BizException e) {
            channelRetMsg.setChannelState(ChannelRetMsg.ChannelState.CONFIRM_FAIL);
            channelRetMsg.setChannelErrCode(e.getApiRes().getCode()+"");
            channelRetMsg.setChannelErrMsg(e.getApiRes().getMsg());
        }catch (Exception e) {
            throw ChannelException.sysError(e.getMessage());
        }
        return channelRetMsg;
    }

    /**
     * 退款权限
     * @param settleType
     * @param applyId
     * @return
     */
    @Override
    public ChannelRefundLimit isRefundLimit(String settleType,String applyId) {
        return super.isRefundLimit(settleType,applyId);
    }

    @Override
    public void checkPlatAccount(RefundOrder refundOrder) {

    }
}
