package com.jeequan.jeepay.pay.ctrl.payorder;

import com.jeequan.jeepay.core.ctrls.AbstractCtrl;
import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.exception.ResponseException;
import com.jeequan.jeepay.core.interfaces.IConfigContextQueryService;
import com.jeequan.jeepay.core.interfaces.paychannel.IPosNoticeService;
import com.jeequan.jeepay.core.model.autopos.ChannelOrderAcceptParams;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.db.entity.RefundOrder;
import com.jeequan.jeepay.pay.service.PayOrderProcessService;
import com.jeequan.jeepay.pay.service.RefundOrderProcessService;
import com.jeequan.jeepay.service.impl.PayOrderService;
import com.jeequan.jeepay.service.impl.RefundOrderService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.Triple;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;

/**
* 智能POS交易通知   用于将订单信息推送到POS，使用POS收款后的异步通知
*
* @author zx
*
* @date 2021/6/8 17:26
*/
@Slf4j
@Controller
public class PosNoticeController extends AbstractCtrl {

    @Autowired private PayOrderService payOrderService;
    @Autowired private IConfigContextQueryService configContextQueryService;
    @Autowired private PayOrderProcessService payOrderProcessService;
    @Autowired private RefundOrderService refundOrderService;
    @Autowired private RefundOrderProcessService refundOrderProcessService;


    /** 智能POS通知入口 **/
    @ResponseBody
    @RequestMapping("/api/pos/pay/notify/{ifCode}")
    public ResponseEntity posNotify(HttpServletRequest request, @PathVariable("ifCode") String ifCode){

        String orderId = null;
        String logPrefix = "进入[" +ifCode+ "]智能POS【订单推送至POS机收款模式】回调";
        log.info("===== {} =====" , logPrefix);

        try {

            // 参数有误
            if(StringUtils.isEmpty(ifCode)){
                return ResponseEntity.badRequest().body("ifCode is empty");
            }

            //查询支付接口是否存在
            IPosNoticeService payNotifyService = SpringBeansUtil.getBean(ifCode + "PosNoticeService", IPosNoticeService.class);

            // 支付通道接口实现不存在
            if(payNotifyService == null){
                log.error("{}, interface not exists ", logPrefix);
                return ResponseEntity.badRequest().body("[" + ifCode + "] interface not exists");
            }

            // 解析订单号 和 请求参数    Triple => <交易类型(PAYMENT-支付 REFUND-退款)，支付订单号，请求数据>
            Triple<String, String, Object> triple = payNotifyService.parseParams(request);
            if(triple == null || StringUtils.isBlank(triple.getMiddle())){ // 解析数据失败， 响应已处理
                log.error("{}, params is null ", logPrefix);
                throw new BizException("解析数据异常！"); //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
            }

            // 解析到订单号
            orderId = triple.getMiddle();

            // 接口验签 && 处理订单数据
            ChannelRetMsg notifyResult;
            // 支付订单
            if (StringUtils.equals(triple.getLeft(), ChannelOrderAcceptParams.TRADE_TYPE_PAYMENT)) {

                PayOrder payOrder = getPayOrder(orderId, logPrefix);

                MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfoV2(payOrder.getMchNo(), payOrder.getAppId(),payOrder.getMchExtNo());

                notifyResult = payNotifyService.payNotice(request, triple.getRight(), payOrder, mchAppConfigContext);

                // 返回null 表明出现异常， 无需处理通知下游等操作。
                if(notifyResult == null || notifyResult.getChannelState() == null || notifyResult.getResponseEntity() == null){
                    log.error("{}, 处理回调事件异常  notifyResult data error, notifyResult ={} ",logPrefix, notifyResult);
                    throw new BizException("处理回调事件异常！"); //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
                }

                payOrderProcessService.handlePayOrder4Channel(notifyResult, payOrder, mchAppConfigContext);

            // 退款订单
            } else if (StringUtils.equals(triple.getLeft(), ChannelOrderAcceptParams.TRADE_TYPE_REFUND)) {

                RefundOrder refundOrder = getRefundOrder(orderId, logPrefix);

                MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfoV2(refundOrder.getMchNo(), refundOrder.getAppId(),refundOrder.getMchExtNo());

                notifyResult = payNotifyService.refundNotice(request, triple.getRight(), refundOrder, mchAppConfigContext);

                // 返回null 表明出现异常， 无需处理通知下游等操作。
                if(notifyResult == null || notifyResult.getChannelState() == null || notifyResult.getResponseEntity() == null){
                    log.error("{}, 处理回调事件异常  notifyResult data error, notifyResult ={} ",logPrefix, notifyResult);
                    throw new BizException("处理回调事件异常！"); //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
                }
                // 处理退款订单
                boolean updateOrderSuccess = refundOrderProcessService.handleRefundOrder4Channel(notifyResult, refundOrder);

                // 更新退款订单 异常
                if(!updateOrderSuccess){
                    log.error("{}, updateOrderSuccess = {} ",logPrefix, updateOrderSuccess);
                    throw ResponseException.buildText("update status error");
                }

            } else {
                throw new BizException("通知类型错误！");
            }

            log.info("===== {}, 订单通知完成。 orderId={}, parseState = {} =====", logPrefix, orderId, notifyResult.getChannelState());

            return notifyResult.getResponseEntity();

        } catch (BizException e) {
            log.error("{}, orderId={}, BizException", logPrefix, orderId, e);
            return ResponseEntity.badRequest().body(e.getMessage());

        } catch (ResponseException e) {
            log.error("{}, orderId={}, ResponseException", logPrefix, orderId, e);
            return e.getResponseEntity();

        } catch (Exception e) {
            log.error("{}, orderId={}, 系统异常", logPrefix, orderId, e);
            return ResponseEntity.badRequest().body(e.getMessage());
        }
    }



    private PayOrder getPayOrder(String orderId, String logPrefix) {
        // 获取订单号 和 订单数据
        PayOrder payOrder = payOrderService.getById(orderId);

        // 订单不存在
        if(payOrder == null){
            log.error("{}, 订单不存在. orderId={} ", logPrefix, orderId);
            throw ResponseException.buildText("order not exists");
        }

        return payOrder;
    }

    private RefundOrder getRefundOrder(String orderId, String logPrefix) {
        // 获取订单号 和 订单数据
        RefundOrder refundOrder = refundOrderService.getById(orderId);

        // 订单不存在
        if(refundOrder == null){
            log.error("{}, 退款订单不存在. refundOrder={} ", logPrefix, refundOrder);
            throw ResponseException.buildText("refund order not exists");
        }

        return refundOrder;
    }

}
