package com.jeequan.jeepay.pay.service;

import com.jeequan.jeepay.core.exception.BizException;
import com.jeequan.jeepay.core.interfaces.paychannel.IDivisionService;
import com.jeequan.jeepay.core.model.context.MchAppConfigContext;
import com.jeequan.jeepay.core.model.rqrs.msg.ChannelRetMsg;
import com.jeequan.jeepay.core.utils.JeepayKit;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.PayOrder;
import com.jeequan.jeepay.db.entity.PayOrderDivisionRecord;
import com.jeequan.jeepay.db.entity.PayOrderDivisionRefundRecord;
import com.jeequan.jeepay.db.entity.RefundOrder;
import com.jeequan.jeepay.service.impl.OrderProfitSettRecordService;
import com.jeequan.jeepay.service.impl.PayOrderDivisionRecordService;
import com.jeequan.jeepay.service.impl.PayOrderDivisionRefundRecordService;
import com.jeequan.jeepay.service.impl.PayOrderService;
import com.jeequan.jeepay.thirdparty.service.ConfigContextQueryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.List;

/***
* 退款 退分业务公共函数
*
* @author terrfly
*
* @date 2022/8/30 15:11
*/
@Service
@Slf4j
public class PayOrderDivisionRefundOrderCommonService {

    @Autowired private PayOrderDivisionRecordService payOrderDivisionRecordService;
    @Autowired private PayOrderDivisionRefundRecordService payOrderDivisionRefundRecordService;
    @Autowired private OrderProfitSettRecordService orderProfitSettRecordService;
    @Autowired private PayOrderService payOrderService;
    @Autowired private ConfigContextQueryService configContextQueryService;


    /** 退款订单回调完成后调用 **/
    public void processDivisionRefundByAfter(RefundOrder refundOrder){

        try {
            IDivisionService divisionService = getDivisionService(refundOrder.getIfCode());
            if(divisionService == null){ // 没有实现该通道的退款
                return ;
            }

            if(!divisionService.divisionRefundIsOrderRefundAfterProc()){ // 返回false 时， 无需执行
                return ;
            }

            SpringBeansUtil.getBean(PayOrderDivisionRefundOrderCommonService.class).delayProcessDivisionRefund(refundOrder);

        } catch (Exception e) {
            log.error("后置退款退分异常！", e);
        }
    }

    @Async
    void delayProcessDivisionRefund(RefundOrder refundOrder) {

        try {
            Thread.sleep(2000 * 60);
            this.processDivisionRefund(refundOrder, configContextQueryService.queryMchInfoAndAppInfoV2(refundOrder.getMchNo(), refundOrder.getAppId(),refundOrder.getMchExtNo()));
        } catch (InterruptedException e) {
            log.error("后置退款退分异常！", e);
        }
    }


    /** 注意： refundBeforePayOrder 是退款发生之前的支付订单信息（此处不可直接查询订单表， 因为如果是后退的话可能已经更改退款金额了。 ） **/
    public void processDivisionRefund(RefundOrder refundOrder, MchAppConfigContext mchAppConfigContext){

        // 查询支付订单
        PayOrder refundBeforePayOrder = payOrderService.getById(refundOrder.getPayOrderId());

        if(refundBeforePayOrder == null){
            throw new BizException("退分业务查询支付订单不存在");
        }

        // 已经退款成功， 那么需要把订单的已成功退款的金额减去, 否则计算的金额有误（ 只有退款中，再退分才会出现该情况。  ）
        if(refundOrder.getState() == RefundOrder.STATE_SUCCESS){
            refundBeforePayOrder.setRefundAmount(refundBeforePayOrder.getRefundAmount() - refundOrder.getRefundAmount());
            if(refundBeforePayOrder.getRefundAmount() < 0){
                refundBeforePayOrder.setRefundAmount(0L);
            }
        }

        // 查询订单是否包含分账成功的账号
        List<PayOrderDivisionRecord> recordList = payOrderDivisionRecordService.list(PayOrderDivisionRecord.gw()
                .eq(PayOrderDivisionRecord::getPayOrderId, refundOrder.getPayOrderId())
                .eq(PayOrderDivisionRecord::getState, PayOrderDivisionRecord.STATE_SUCCESS)
        );

        // 不包含分账订单
        if(recordList.isEmpty()){
            return ;
        }

        // 遍历分账记录
        for (PayOrderDivisionRecord record : recordList) {

            try {

                //插入分账退回记录
                PayOrderDivisionRefundRecord divRefundRecord = genAndSaveRecord(record, refundOrder, refundBeforePayOrder);

                //调起分账退回接口
                //获取退款接口
                IDivisionService divisionService = getDivisionService(refundBeforePayOrder.getIfCode());
                if(divisionService == null){
                    throw new BizException("当前通道不支持分账回退！");
                }

                // 更新状态
                PayOrderDivisionRefundRecord updateRecord = new PayOrderDivisionRefundRecord();
                updateRecord.setDivisionRefundId(divRefundRecord.getDivisionRefundId());

                try {

                    // 退分金额 为 0 ， 直接改为成功。
                    if(divRefundRecord.getDivisionRefundAmount() <= 0){

                        updateRecord.setState(PayOrderDivisionRefundRecord.STATE_SUCCESS);

                    }else{ // 需要调用接口， 完成退分逻辑

                        ChannelRetMsg channelRetMsg = divisionService.divisionRefund(record, divRefundRecord, refundOrder, refundBeforePayOrder, mchAppConfigContext);

                        // 退回成功
                        if(channelRetMsg.getChannelState() == ChannelRetMsg.ChannelState.CONFIRM_SUCCESS){
                            updateRecord.setState(PayOrderDivisionRefundRecord.STATE_SUCCESS);
                            updateRecord.setChannelOrderNo(channelRetMsg.getChannelOrderId());
                        }else{ // 退回失败
                            updateRecord.setState(PayOrderDivisionRefundRecord.STATE_FAIL);
                            updateRecord.setChannelOrderNo(channelRetMsg.getChannelOrderId());
                            updateRecord.setErrCode(channelRetMsg.getChannelErrCode());
                            updateRecord.setErrMsg(channelRetMsg.getChannelErrMsg());
                        }
                    }

                } catch (Exception e) {
                    updateRecord.setState(PayOrderDivisionRefundRecord.STATE_FAIL);
                    updateRecord.setErrMsg(e.getMessage());
                }

                // 更新记录
                payOrderDivisionRefundRecordService.updateRefundRecordAndDivisionRecord(updateRecord, divRefundRecord.getDivisionRecordId(), divRefundRecord.getDivisionRefundAmount());

            }catch (Exception e){
                log.error("分账退回操作失败, recordId={}, accName={}", record.getRecordId(), record.getAccName(), e);
            }
        }
    }

    /** 插入分账退回记录 **/
    private PayOrderDivisionRefundRecord genAndSaveRecord(PayOrderDivisionRecord record, RefundOrder refundOrder, PayOrder refundBeforePayOrder){

        PayOrderDivisionRefundRecord refundRecord = payOrderDivisionRefundRecordService.genRecord(record, refundOrder, refundBeforePayOrder);
        payOrderDivisionRefundRecordService.save(refundRecord);
        return refundRecord;
    }

    private IDivisionService getDivisionService(String ifCode){
        IDivisionService divisionService = SpringBeansUtil.getBean(JeepayKit.getIfCodeOrigin(ifCode) + "DivisionService", IDivisionService.class);
        return divisionService;
    }
}
