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

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.cashout.IChannelCashoutNoticeService;
import com.jeequan.jeepay.core.model.cashout.CashoutRetMsg;
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.ChannelAccountCashoutRecord;
import com.jeequan.jeepay.service.impl.ChannelAccountCashoutRecordService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.tuple.MutablePair;
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;

/**
* 渠道提现通知解析实现
*
* @author zx
*
* @date 2021/6/8 17:26
*/
@Slf4j
@Controller
public class MchChannelCashoutNoticeController extends AbstractCtrl {

    @Autowired private ChannelAccountCashoutRecordService cashoutRecordService;
    @Autowired private IConfigContextQueryService configContextQueryService;


    /** 提现回调入口 **/
    @ResponseBody
    @RequestMapping(value= {"/api/channel/cashout/notify/{ifCode}", "/api/channel/cashout/notify/{ifCode}/{rid}"})
    public ResponseEntity doNotify(HttpServletRequest request, @PathVariable("ifCode") String ifCode, @PathVariable(value = "rid", required = false) String urlRid){

        String rid = null;
        String logPrefix = "进入[" +ifCode+ "]提现回调：提现urlRid：["+ StringUtils.defaultIfEmpty(urlRid, "") + "] ";
        log.info("===== {} =====" , logPrefix);

        try {

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

            //查询通知接口是否存在
            IChannelCashoutNoticeService cashoutNoticeService = SpringBeansUtil.getBean(ifCode + "ChannelCashoutNoticeService", IChannelCashoutNoticeService.class);

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

            // 解析提现单号 和 请求参数
            MutablePair<String, Object> mutablePair = cashoutNoticeService.parseParams(request, urlRid);
            if(mutablePair == null){ // 解析数据失败， 响应已处理
                log.error("{}, mutablePair is null ", logPrefix);
                throw new BizException("解析数据异常！"); //需要实现类自行抛出ResponseException, 不应该在这抛此异常。
            }

            //解析到提现单号
            rid = mutablePair.left;
            log.info("{}, 解析数据为：rid:{}, params:{}", logPrefix, rid, mutablePair.getRight());

            //获取提现单号 和 提现单数据
            ChannelAccountCashoutRecord cashoutRecord = cashoutRecordService.getById(rid);

            // 提现单不存在
            if(cashoutRecord == null){
                log.error("{}, 提现单不存在. rid={} ", logPrefix, rid);
                return ResponseEntity.badRequest().body("cashout record not exists");
            }

            //查询出商户应用的配置信息
            MchAppConfigContext mchAppConfigContext = configContextQueryService.queryMchInfoAndAppInfoV2(cashoutRecord.getMchNo(), cashoutRecord.getAppId(),cashoutRecord.getMchExtNo());


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

            boolean updateOrderSuccess = true; //默认更新成功
            // 提现单是 【提现中状态】
            if(cashoutRecord.getState() == ChannelAccountCashoutRecord.CASHOUT_STATE_ING) {
                // 渠道提现单号
                cashoutRecord.setChannelRid(cashoutRetMsg.getChannelOrderId());
                // 明确成功
                if(ChannelRetMsg.ChannelState.CONFIRM_SUCCESS == cashoutRetMsg.getChannelState()) {

                    updateOrderSuccess = cashoutRecordService.updateIng2Success(rid, cashoutRetMsg.getChannelOrderId(), cashoutRetMsg.getBankName(), cashoutRetMsg.getBankAccount(), cashoutRetMsg.getBankAccountName());

                //明确失败
                }else if(ChannelRetMsg.ChannelState.CONFIRM_FAIL == cashoutRetMsg.getChannelState()) {
                    String failMsg = String.format("failInfo=[code=%s, msg=%s]", cashoutRetMsg.getChannelErrCode(), cashoutRetMsg.getChannelErrMsg());
                    updateOrderSuccess = cashoutRecordService.updateIng2Fail(rid, failMsg);
                }
            }

            // 更新提现单 异常
            if(!updateOrderSuccess){
                log.error("{}, updateOrderSuccess = {} ",logPrefix, updateOrderSuccess);
                return ResponseEntity.badRequest().body("update error");
            }

            log.info("===== {}, 提现单通知完成。 rid={}, parseState = {} =====", logPrefix, rid, cashoutRetMsg.getChannelState());

            return cashoutRetMsg.getResponseEntity();

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

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

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

}
