package com.jeequan.jeepay.bill.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.interfaces.bill.IReconciliationService;
import com.jeequan.jeepay.core.model.bill.ChannelBillRQ;
import com.jeequan.jeepay.core.utils.SpringBeansUtil;
import com.jeequan.jeepay.db.entity.CheckBatch;
import com.jeequan.jeepay.db.entity.PayInterfaceDefine;
import com.jeequan.jeepay.service.impl.CheckBatchService;
import com.jeequan.jeepay.service.impl.PayInterfaceConfigService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/***
* 对账接口
*
* @author zx
* @date 2022/3/12 14:54
*/
@Service
@Slf4j
public class ReconciliationRestockService {

    @Autowired private PayInterfaceConfigService payInterfaceConfigService;
    @Autowired private CheckBatchService checkBatchService;

    /**
     * 重新对账，解决对账任务中断或某些支付接口账单下载/解析失败问题
     * */
    public void queryChannelBillAndCheck(PayInterfaceDefine payInterfaceDefine, Date billDate) {

        String ifCode = payInterfaceDefine.getIfCode();

        // 查询去重的渠道商户号 和 本地支付配置
        List<ChannelBillRQ> channelBillRQList = buildDistinctIfParams(payInterfaceDefine);
        if(CollUtil.isEmpty(channelBillRQList)){
            log.info("支付接口：{}，无支付参数配置！", ifCode);
            return;
        }

        // 查询  解析失败&&渠道号   的对账批次
        List<CheckBatch> checkBatchList = checkBatchService.list(CheckBatch.gw()
                .eq(CheckBatch::getIfCode, ifCode)
                .eq(CheckBatch::getReleaseState, CS.YES)
                .ge(CheckBatch::getBillDate, DateUtil.beginOfDay(billDate))
                .le(CheckBatch::getBillDate, DateUtil.endOfDay(billDate))
        );

        // 全部 对账解析失败的商户号
        List<String> successChannelMchNoList = checkBatchList.stream().map(CheckBatch::getChannelMchNo).collect(Collectors.toList());

        // 解析失败的批次重新对账
        for (ChannelBillRQ channelBillRQ : channelBillRQList) {
            if (CollUtil.isEmpty(checkBatchList)) {
                checkBills4ReleaseFailBatch(ifCode, billDate, channelBillRQ);
                continue;
            }

            if (!successChannelMchNoList.contains(channelBillRQ.getChannelMchNo())) {
                checkBills4ReleaseFailBatch(ifCode, billDate, channelBillRQ);
            }
        }

    }


    /** 构建全部服务商、商户的渠道商户号与服务商或应用的配置关系 */
    public List<ChannelBillRQ> buildDistinctIfParams(PayInterfaceDefine payInterfaceDefine) {
        List<ChannelBillRQ> channelBillRQList = new ArrayList<>();
        if (payInterfaceDefine.getIsIsvMode() != null && payInterfaceDefine.getIsIsvMode() == CS.YES) {
            channelBillRQList.addAll(payInterfaceConfigService.selectDistinctIsvIfParams(payInterfaceDefine.getIfCode())); // 查询服务商渠道号 与 服务商号及配置参数对应关系
            channelBillRQList.addAll(payInterfaceConfigService.selectDistinctIsvSubMchIfParams(payInterfaceDefine.getIfCode())); // 查询特约商户 与 商户应用及配置参数对应关系
        }else if (payInterfaceDefine.getIsMchMode() != null && payInterfaceDefine.getIsMchMode() == CS.YES){
            channelBillRQList.addAll(payInterfaceConfigService.selectDistinctNormalMchIfParams(payInterfaceDefine.getIfCode())); // 查询普通商户 与 商户应用及配置参数对应关系
        }
        return channelBillRQList;
    }

    /** 解析失败的批次  补充对账 */
    public void checkBills4ReleaseFailBatch(String ifCode, Date billDate, ChannelBillRQ channelBillRQ) {

        try {
            com.jeequan.jeepay.core.entity.CheckBatch coreCheckBatch = new CheckBatch();
            coreCheckBatch.setBatchNo(checkBatchService.getBatchNo(ifCode, channelBillRQ.getChannelMchNo(), billDate));
            coreCheckBatch.setIfCode(ifCode);
            coreCheckBatch.setBillDate(billDate);
            coreCheckBatch.setChannelMchNo(channelBillRQ.getChannelMchNo());
            coreCheckBatch.setReleaseState(CS.NO);

            IReconciliationService reconciliationService = SpringBeansUtil.getBean("reconciliationService", IReconciliationService.class);
            reconciliationService.reloadBill4Batch(coreCheckBatch, "release");

        }catch (Exception e) {
            log.error("对账单处理失败，支付接口：{}，渠道商户号：{}，对账日期：{}", ifCode, channelBillRQ.getChannelMchNo(), billDate, e);
        }
    }

    /** 处理差异 */
    public void processCheckDiffBills(Date billDate) {
        IReconciliationService reconciliationService = SpringBeansUtil.getBean("reconciliationService", IReconciliationService.class);
        reconciliationService.processCheckDiffBills(billDate);
    }
}
