package com.jeequan.jeepay.mgr.ctrl.payconfig;

import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.jeequan.jeepay.converter.BaseConverter;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.constants.ConstWord;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
import com.jeequan.jeepay.db.entity.*;
import com.jeequan.jeepay.mgr.ctrl.CommonCtrl;
import com.jeequan.jeepay.model.RateConfigSimple;
import com.jeequan.jeepay.service.impl.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.*;

/**
 * 费率配置信息
 *
 * @author terrfly
 * @since 2022/3/21 0:13
 */
@RestController
@RequestMapping("/api/rateConfig")
public class RateConfigController extends CommonCtrl {

    @Autowired
    private MchAppService mchAppService;
    @Autowired
    private RateConfigService rateConfigService;
    @Autowired
    private PayWayService payWayService;

    @Autowired
    private IsvUserConnService isvUserConnService;

    @Autowired
    private BaseConverter baseConverter;
    @Autowired
    private RateConfigV2Service rateConfigV2Service;

    /**
     * 查询所有可配置的支付方式  payways
     **/
    @GetMapping("/payways")
    public ApiRes payways() {

        String ifCode = getValStringRequired(ConstWord.IF_CODE); // ifCode
        String infoId = getValStringRequired(ConstWord.INFO_ID); // infoId
        String isvNo = getValString(ConstWord.ISV_NO); // isvNo
        String configMode = getValStringRequired(ConstWord.CONFIG_MODE); // 设置类型
        Integer range = getValInteger("range");
        String mccCode = getValString("mccCode");

        // 商户服务商或者服务商的父ID (用于过滤掉关闭的支付方式)
        String belongAgentNo = null;
        String belongIsvNo = null;

        String mchAppId = getValString(ConstWord.APP_ID);
        if (!ObjUtil.isEmpty(mchAppId)) {
            MchAppEntity mchApp = mchAppService.getById(mchAppId);
            range = mchApp.getRange();
            mccCode = mchApp.getMccCode();
        }

        // 是否仅显示 支持进件的支付方式（用作进件使用）
        boolean isOnlyApplymentSupport = RateConfig.CONFIG_MODE_MGRAPPLYMENT.equals(configMode);

        // 运营平台  配置 服务商显示全部的就可以。
        if (RateConfig.CONFIG_MODE_MGRISV.equals(configMode)) {
            isvNo = infoId;
            // 给服务商配置， 显示所有的就可以。

            // 运营平台配置服务商的费率
        } else if (RateConfig.CONFIG_MODE_MGRAGENT.equals(configMode)) {

            AgentInfo agentInfo = agentInfoService.getById(infoId);
            belongAgentNo = agentInfo.getPid();

            belongIsvNo = isvNo;
            // 运营平台 配置 商户应用费率 || 商户发起的进件
        } else if (RateConfig.CONFIG_MODE_MGRMCH.equals(configMode) || RateConfig.CONFIG_MODE_MGRAPPLYMENT.equals(configMode)) {

            String mchNo;

            // 运营平台进件模式 :  infoId =  applyId_mchNo 的拼接方式。
            if (RateConfig.CONFIG_MODE_MGRAPPLYMENT.equals(configMode)) {
                mchNo = infoId.split("_")[1];
            } else {
                mchNo = infoId;
            }

            MchInfo mchInfo = mchInfoService.getById(mchNo);

            belongAgentNo = mchInfo.getAgentNo();
        }

        return ApiRes.page(payWayService.queryWayListByRate(ifCode, belongIsvNo, belongAgentNo, isOnlyApplymentSupport, range, mccCode, isvNo));
    }


    /**
     * 查询当前已经配置的列表
     **/
    @GetMapping(value = "/savedMapData")
    public ApiRes savedMapData() {
        String ifCode = getValStringRequired("ifCode"); // ifCode
        String infoId = getValStringRequired("infoId"); // infoId
        String configMode = getValStringRequired("configMode"); // 设置类型
        String isvNo = getValString("isvNo"); // 设置类型
        Integer range = getValInteger("range");
        String mccCode = getValString("mccCode");

        String mchAppId = getValString("appId");
        if (!ObjUtil.isEmpty(mchAppId)) {
            MchAppEntity mchApp = mchAppService.getById(mchAppId);
            range = mchApp.getRange();
            mccCode = mchApp.getMccCode();
        }

        // 配置渠道商费率
        if (RateConfig.CONFIG_MODE_MGRISV.equals(configMode)) {
            Map<String, Object> result = new HashMap<>();
            result.put(RateConfig.ISVCOST, rateConfigService.queryPaywayFeeMap(infoId + "_" + RateConfig.ISVCOST, commonGetInfoType(configMode), ifCode, range, mccCode, infoId));
            result.put(RateConfig.AGENTDEF, rateConfigService.queryPaywayFeeMap(infoId + "_" + RateConfig.AGENTDEF, commonGetInfoType(configMode), ifCode, range, mccCode, infoId));
            result.put(RateConfig.MCHAPPLYDEF, rateConfigService.queryPaywayFeeMap(infoId + "_" + RateConfig.MCHAPPLYDEF, commonGetInfoType(configMode), ifCode, range, mccCode, infoId));
            result.put(RateConfig.AGENTMAX, rateConfigService.queryPaywayFeeMap(infoId + "_" + RateConfig.AGENTMAX, commonGetInfoType(configMode), ifCode, range, mccCode, infoId));
            result.put(RateConfig.MCHAPPLYMAX, rateConfigService.queryPaywayFeeMap(infoId + "_" + RateConfig.MCHAPPLYMAX, commonGetInfoType(configMode), ifCode, range, mccCode, infoId));

            return ApiRes.ok(result);
        }

        // 配置服务商费率
        if (RateConfig.CONFIG_MODE_MGRAGENT.equals(configMode)) {
            Map<String, Object> result = new HashMap<>();
            Map<String, PaywayFee> agentRate = rateConfigService.queryPaywayFeeMap(infoId + "_" + RateConfig.AGENTRATE, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo);
            result.put(RateConfig.AGENTRATE, agentRate);

            result.put(RateConfig.MCHAPPLYMAX, rateConfigService.queryPaywayFeeMap(infoId + "_" + RateConfig.MCHAPPLYMAX, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo));

            AgentInfo agentInfo = agentInfoService.getById(infoId);

            Map<String, PaywayFee> agentRateDef = null;
            if (agentInfo.getPid() == null) {
                agentRateDef = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByAgentDef(infoId), CS.SYS_ROLE_TYPE.ISV, ifCode, range, mccCode, isvNo);
            } else {
                agentRateDef = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByAgentDef(infoId), CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo);
            }

            result.put(RateConfig.AGENTDEF, agentRateDef);

            result.put(RateConfig.MCHAPPLYDEF, rateConfigService.queryPaywayFeeMap(infoId + "_" + RateConfig.MCHAPPLYDEF, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo));

            // 查询渠道商底价
            result.put(RateConfig.READONLYISVCOST, rateConfigService.queryPaywayFeeMap(isvNo + "_" + RateConfig.ISVCOST, CS.SYS_ROLE_TYPE.ISV, ifCode, range, mccCode, isvNo));

            Map<String, PaywayFee> parentDefRate = null;
            // 查询上级服务商的费率
            if (!ObjUtil.isEmpty(agentInfo.getPid())) {
                result.put(RateConfig.READONLYPARENTAGENT, rateConfigService.queryPaywayFeeMap(agentInfo.getPid() + "_" + RateConfig.AGENTRATE, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo));

                // 默认费率
                parentDefRate = rateConfigService.queryPaywayFeeMap(agentInfo.getPid() + "_" + RateConfig.AGENTDEF, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo);
            } else { // 无上级服务商， 查询服务商配置的。
                // 默认费率
                parentDefRate = rateConfigService.queryPaywayFeeMap(isvNo + "_" + RateConfig.AGENTDEF, CS.SYS_ROLE_TYPE.ISV, ifCode, range, mccCode, isvNo);
            }

            result.put(RateConfig.READONLYPARENTDEFRATE, parentDefRate);

            PaywayFee.resetData(agentRate, baseConverter.newPaywayFeeMap(parentDefRate));

            // 默认下级代理最大费率
            if (ObjUtil.isEmpty(agentInfo.getPid())) {
                result.put(RateConfig.READONLYPARENTSUBAGENTMAX, rateConfigService.queryPaywayFeeMap(isvNo + "_" + RateConfig.AGENTMAX, CS.SYS_ROLE_TYPE.ISV, ifCode, range, mccCode, isvNo));
            } else {
                result.put(RateConfig.READONLYPARENTSUBAGENTMAX, rateConfigService.queryPaywayFeeMap(agentInfo.getPid() + "_" + RateConfig.AGENTMAX, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo));
            }

            // 商户最大费率
            if (ObjUtil.isEmpty(agentInfo.getPid())) {
                result.put(RateConfig.READONLYPARENTMCHMAX, rateConfigService.queryPaywayFeeMap(isvNo + "_" + RateConfig.MCHAPPLYMAX, CS.SYS_ROLE_TYPE.ISV, ifCode, range, mccCode, isvNo));
            } else {
                result.put(RateConfig.READONLYPARENTMCHMAX, rateConfigService.queryPaywayFeeMap(agentInfo.getPid() + "_" + RateConfig.MCHAPPLYMAX, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo));
            }

            return ApiRes.ok(result);
        }

        // 配置商户费率 || 服务商进件模式
        if (RateConfig.CONFIG_MODE_MGRMCH.equals(configMode) || RateConfig.CONFIG_MODE_MGRAPPLYMENT.equals(configMode)) {
            Assert.notBlank(isvNo, "渠道号不能为空");

            Map<String, Object> result = new HashMap<>();

            String mchNo;
            String applyId = "";

            // 运营平台进件模式 :  infoId =  applyId_mchNo 的拼接方式。
            if (RateConfig.CONFIG_MODE_MGRAPPLYMENT.equals(configMode)) {
                applyId = infoId.split("_")[0];
                mchNo = infoId.split("_")[1];
            } else {
                // 不再使用应用关联费率，直接用用户/商户关联费率
                mchNo = infoId;
            }

            Map<String, PaywayFee> mchRateMap = null;
            // 查询已经配置的信息
            if (RateConfig.CONFIG_MODE_MGRAPPLYMENT.equals(configMode) && !ObjUtil.isEmpty(applyId)) {  // 运营平台进件模式
//                mchRateMap = rateConfigService.queryPaywayFeeMapByApplyment(applyId);
                // 此处费率不从商户信息里面取了
                mchRateMap = rateConfigService.queryPaywayFeeMap(applyId, CS.SYS_ROLE_TYPE.MCH_APPLYMENT, ifCode, range, mccCode, isvNo);
            } else {
                // 这里直接取服务商给用户配置的费率
                mchRateMap = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByMchApp(mchNo), CS.SYS_ROLE_TYPE.MCH_APP, ifCode, range, mccCode, isvNo);
            }

            result.put(RateConfig.MCHRATE, mchRateMap);

            MchInfo mchInfo = mchInfoService.getById(mchNo);

            // 特约商户
            if (mchInfo.getType() == CS.MCH_TYPE_ISVSUB) {
                // 查询渠道商底价
                result.put(RateConfig.READONLYISVCOST, rateConfigService.queryPaywayFeeMap(isvNo + "_" + RateConfig.ISVCOST, CS.SYS_ROLE_TYPE.ISV, ifCode, range, mccCode, isvNo));

                // 查询上级服务商的费率
                if (!ObjUtil.isEmpty(mchInfo.getAgentNo())) {
                    result.put(RateConfig.READONLYPARENTAGENT, rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByAgent(mchInfo.getAgentNo()), CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo));
                }

                Map<String, PaywayFee> parentDefRate = null;
                // 默认费率
                if (ObjUtil.isEmpty(mchInfo.getAgentNo())) {
                    parentDefRate = rateConfigService.queryPaywayFeeMap(isvNo + "_" + RateConfig.MCHAPPLYDEF, CS.SYS_ROLE_TYPE.ISV, ifCode, range, mccCode, isvNo);
                } else {
                    parentDefRate = rateConfigService.queryPaywayFeeMap(mchInfo.getAgentNo() + "_" + RateConfig.MCHAPPLYDEF, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo);
                }

                result.put(RateConfig.READONLYPARENTDEFRATE, parentDefRate);

                // 默认商户最大费率
                if (ObjUtil.isEmpty(mchInfo.getAgentNo())) {
                    result.put(RateConfig.READONLYPARENTMCHMAX, rateConfigService.queryPaywayFeeMap(isvNo + "_" + RateConfig.MCHAPPLYMAX, CS.SYS_ROLE_TYPE.ISV, ifCode, range, mccCode, isvNo));
                } else {
                    result.put(RateConfig.READONLYPARENTMCHMAX, rateConfigService.queryPaywayFeeMap(mchInfo.getAgentNo() + "_" + RateConfig.MCHAPPLYMAX, CS.SYS_ROLE_TYPE.AGENT, ifCode, range, mccCode, isvNo));
                }

                // 商户费率为空时，将默认费率设置为商户费率
                if (ObjUtil.isEmpty(result.get(RateConfig.MCHRATE))) {
                    result.put(RateConfig.MCHRATE, result.get(RateConfig.READONLYPARENTDEFRATE));
                }

//                if (ObjUtil.isEmpty(result.get(RateConfig.MCHRATE))) {
//                    throw new BizException("未获取到商户费率，且其上级服务商未配置默认商户费率");
//                }

                // 后续添加跟渠道费率配置对比
                PaywayFee.resetData(mchRateMap, baseConverter.newPaywayFeeMap(parentDefRate));
            }

            return ApiRes.ok(result);
        }

        return ApiRes.ok();
    }

    /**
     * 保存费率信息
     **/
    @MethodLog(remark = "配置服务商费率")
    @PostMapping(value = "")
    public ApiRes reset() {

        // 需要删除的集合， 比如：  配置渠道商底价， 关闭了某些渠道， 那么需要将下属的配置删除掉。
        List<RateConfig> delList = new ArrayList<>();

        String configMode = getValStringRequired("configMode");

        // 运营平台： 是否 不校验商户规则
        Byte noCheckRuleFlag = getValByteDefault("noCheckRuleFlag", CS.NO);

        // 主对象
        RateConfig mainRateConfig = getObject(RateConfig.class);

        // 必须设置infoType, 检查费率会使用
        mainRateConfig.setInfoType(commonGetInfoType(configMode));

        // 配置渠道费率
        if (RateConfig.CONFIG_MODE_MGRISV.equals(configMode)) {
            mainRateConfig.setIsvNo(mainRateConfig.getInfoId());
        }

        Map<String, PaywayFee> isvCostMap = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByIsvCost(mainRateConfig.getIsvNo()), CS.SYS_ROLE_TYPE.ISV,
                mainRateConfig.getIfCode(), mainRateConfig.getRange(), mainRateConfig.getMccCode(), mainRateConfig.getIsvNo());

        List<RateConfig> list = new ArrayList<>();

        // 渠道商底价 infoId = ISVNO_ISVCOST   infoType = 1(服务商)
        if (!ObjUtil.isEmpty(mainRateConfig.extv().getString(RateConfig.ISVCOST))) {
            JSON.parseArray(mainRateConfig.extv().getString(RateConfig.ISVCOST), PaywayFee.class)
                    .forEach(r -> list.add(getFillInfoIdAndType(mainRateConfig, r, RateConfig.ISVCOST, configMode)));

            // 配置服务商需要删除 下属配置。
            delList = this.genDelRateConfigList(mainRateConfig.getInfoId(), null, mainRateConfig.getIfCode());
        }

        // 服务商默认费率 infoId = ISVNO_AGENTDEF  infoType = 1(服务商)
        if (!ObjUtil.isEmpty(mainRateConfig.extv().getString(RateConfig.AGENTDEF))) {
            JSON.parseArray(mainRateConfig.extv().getString(RateConfig.AGENTDEF), PaywayFee.class)
                    .forEach(r -> list.add(getFillInfoIdAndType(mainRateConfig, r, RateConfig.AGENTDEF, configMode)));
        }

        // 服务商最大费率 infoId = ISVNO_AGENTMAX  infoType = 1(服务商)
        if (!ObjUtil.isEmpty(mainRateConfig.extv().getString(RateConfig.AGENTMAX))) {
            JSON.parseArray(mainRateConfig.extv().getString(RateConfig.AGENTMAX), PaywayFee.class)
                    .forEach(r -> list.add(getFillInfoIdAndType(mainRateConfig, r, RateConfig.AGENTMAX, configMode)));
        }


        // 商户默认费率 infoId = ISVNO_MCHAPPLYDEF   infoType = 1(服务商)
        if (!ObjUtil.isEmpty(mainRateConfig.extv().getString(RateConfig.MCHAPPLYDEF))) {
            JSON.parseArray(mainRateConfig.extv().getString(RateConfig.MCHAPPLYDEF), PaywayFee.class)
                    .forEach(r -> list.add(getFillInfoIdAndType(mainRateConfig, r, RateConfig.MCHAPPLYDEF, configMode)));
        }

        // 商户最大费率 infoId = ISVNO_MCHAPPLYMAX  infoType = 1(服务商)
        if (!ObjUtil.isEmpty(mainRateConfig.extv().getString(RateConfig.MCHAPPLYMAX))) {
            JSON.parseArray(mainRateConfig.extv().getString(RateConfig.MCHAPPLYMAX), PaywayFee.class)
                    .forEach(r -> list.add(getFillInfoIdAndType(mainRateConfig, r, RateConfig.MCHAPPLYMAX, configMode)));
        }

        // 商户费率
        if (!ObjUtil.isEmpty(mainRateConfig.extv().getString(RateConfig.MCHRATE))) {
            JSON.parseArray(mainRateConfig.extv().getString(RateConfig.MCHRATE), PaywayFee.class)
                    .forEach(r -> list.add(getFillInfoIdAndType(mainRateConfig, r, RateConfig.MCHRATE, configMode)));
        }

        // 服务商费率
        if (!ObjUtil.isEmpty(mainRateConfig.extv().getString(RateConfig.AGENTRATE))) {
            JSON.parseArray(mainRateConfig.extv().getString(RateConfig.AGENTRATE), PaywayFee.class)
                    .forEach(r -> {
                        PaywayFee paywayFee = isvCostMap.get(r.getWayCode());
                        Optional.ofNullable(paywayFee).ifPresent(it -> r.setApplymentSupport(paywayFee.getApplymentSupport()));
                        list.add(getFillInfoIdAndType(mainRateConfig, r, RateConfig.AGENTRATE, configMode));
                    });

            // 配置 服务商 需要删除 下属配置。
            delList = this.genDelRateConfigList(null, mainRateConfig.getInfoId(), mainRateConfig.getIfCode());
        }

        LambdaQueryWrapper<RateConfig> delWrapper = Wrappers.lambdaQuery();
        delWrapper.eq(RateConfig::getIfCode, mainRateConfig.getIfCode());
        delWrapper.eq(RateConfig::getIsvNo, mainRateConfig.getIsvNo());
        delWrapper.eq(RateConfig::getInfoType, commonGetInfoType(configMode));
        delWrapper.eq(mainRateConfig.getRange() != null, RateConfig::getRange, mainRateConfig.getRange());
        delWrapper.eq(!ObjUtil.isEmpty(mainRateConfig.getMccCode()), RateConfig::getMccCode, mainRateConfig.getMccCode());
        delWrapper.in(RateConfig::getInfoId, commonGetInfoId(configMode, mainRateConfig.getInfoId()));

        rateConfigService.resetRate(list, delWrapper, mainRateConfig, (noCheckRuleFlag == CS.YES), delList);
        return ApiRes.ok();
    }


    private RateConfig getFillInfoIdAndType(RateConfig mainRateConfig, PaywayFee paywayFee, String infoSuffix, String configMode) {

        RateConfig result = new RateConfig();
        result.setInfoId(mainRateConfig.getInfoId() + "_" + infoSuffix);
        result.setIfCode(mainRateConfig.getIfCode());
        result.setMccCode(mainRateConfig.getMccCode());
        result.setRange(mainRateConfig.getRange());
        result.setIsvNo(mainRateConfig.getIsvNo());
        result.setWayCode(paywayFee.getWayCode());
        result.setFeeType(paywayFee.getFeeType());
        result.setFeeRate(paywayFee.getFeeRate());
        result.setApplymentSupport(paywayFee.getApplymentSupport());
        result.setPaywayFeeDetail((JSONObject) JSON.toJSON(paywayFee));
        result.setInfoType(commonGetInfoType(configMode));

        return result;
    }


    private String commonGetInfoType(String configMode) {

        //设置服务商信息
        if (RateConfig.CONFIG_MODE_MGRISV.equals(configMode)) {

            return CS.SYS_ROLE_TYPE.ISV;

        } else if (RateConfig.CONFIG_MODE_MGRAGENT.equals(configMode)) {

            return CS.SYS_ROLE_TYPE.AGENT;

        } else if (RateConfig.CONFIG_MODE_MGRMCH.equals(configMode)) {

            return CS.SYS_ROLE_TYPE.MCH_APP;

        } else if (RateConfig.CONFIG_MODE_AGENTSELF.equals(configMode)) {

            return CS.SYS_ROLE_TYPE.AGENT;

        } else if (RateConfig.CONFIG_MODE_AGENTSUBAGENT.equals(configMode)) {

            return CS.SYS_ROLE_TYPE.AGENT;

        } else if (RateConfig.CONFIG_MODE_AGENTEMCH.equals(configMode)) {

            return CS.SYS_ROLE_TYPE.MCH_APP;

        }

        return "";
    }

    private List<String> commonGetInfoId(String configMode, String infoId) {

        //设置服务商信息
        if (RateConfig.CONFIG_MODE_MGRISV.equals(configMode)) {

            return Arrays.asList(
                    (infoId + "_" + RateConfig.ISVCOST),
                    (infoId + "_" + RateConfig.AGENTDEF),
                    (infoId + "_" + RateConfig.AGENTMAX),
                    (infoId + "_" + RateConfig.MCHAPPLYDEF),
                    (infoId + "_" + RateConfig.MCHAPPLYMAX)
            );

        } else if (RateConfig.CONFIG_MODE_MGRAGENT.equals(configMode)) {

            return Arrays.asList(
                    (infoId + "_" + RateConfig.AGENTRATE),
                    (infoId + "_" + RateConfig.AGENTDEF),
                    (infoId + "_" + RateConfig.AGENTMAX),
                    (infoId + "_" + RateConfig.MCHAPPLYDEF),
                    (infoId + "_" + RateConfig.MCHAPPLYMAX)
            );

        } else if (RateConfig.CONFIG_MODE_MGRMCH.equals(configMode)) {

            return Collections.singletonList((infoId + "_" + RateConfig.MCHRATE));

        } else if (RateConfig.CONFIG_MODE_AGENTSELF.equals(configMode)) {

            return Arrays.asList(
                    (infoId + "_" + RateConfig.AGENTDEF),
                    (infoId + "_" + RateConfig.MCHAPPLYDEF),
                    (infoId + "_" + RateConfig.MCHAPPLYMAX)
            );

        } else if (RateConfig.CONFIG_MODE_AGENTSUBAGENT.equals(configMode)) {

            return Arrays.asList(
                    (infoId + "_" + RateConfig.AGENTRATE),
                    (infoId + "_" + RateConfig.MCHAPPLYMAX)
            );

        } else if (RateConfig.CONFIG_MODE_AGENTEMCH.equals(configMode)) {

            return Collections.singletonList(
                    (infoId + "_" + RateConfig.MCHRATE)
            );

        }

        return new ArrayList<>();
    }


    /**
     * 获取待删除的列表集合  info_id/ info_type  if_code  way_code
     * <p>
     * 以下三个场景需要判断：
     * 渠道商底价
     * 运营平台 --> 设置服务商费率
     * 服务商 配置 下级服务商费率 (服务商)
     **/
    private List<RateConfig> genDelRateConfigList(String isvNo, String agentNo, String ifCode) {

        String delPaywayCodeListStr = getValString("delPaywayCodeListStr");
        if (StringUtils.isEmpty(delPaywayCodeListStr)) {
            return Collections.emptyList();
        }

        List<String> delWayCodeList = JSON.parseArray(delPaywayCodeListStr, String.class);

        // 没有待删除的列表
        if (delWayCodeList.isEmpty()) {
            return Collections.emptyList();
        }

        List<RateConfig> result = new ArrayList<>();


        Set<String> allAgentNoList = new HashSet<>();
        Set<String> allMchNoList = new HashSet<>();
        Set<String> allAppIdList = new HashSet<>();


        // 服务商不为空
        if (!ObjUtil.isEmpty(isvNo)) {


            // 判断是否支持服务商
            if (SysConfigService.IS_HAS_AGENT_ENT) {

                // 查询所有的服务商列表 ( 一级服务商 )
                agentInfoService.list(AgentInfo.gw().select(AgentInfo::getAgentNo).eq(AgentInfo::getIsvNo, isvNo)).forEach(r -> allAgentNoList.add(r.getAgentNo()));

            }

            // 查询所有的商户列表  [ 无需查询服务商的所属了， 已经是全部服务商下的商户了。  ]
            isvUserConnService.lambdaQuery().eq(IsvUserConnEntity::getIsvNo, isvNo)
                    .eq(IsvUserConnEntity::getStatus, CS.YES)
                    .eq(IsvUserConnEntity::getInfoType, CS.SYS_ROLE_TYPE.MCH)
                    .list()
                    .forEach(r -> allMchNoList.add(r.getInfoId()));

            // 查询下级服务商的 子服务商【递归】
            Set<String> tempAgentNoSet = new HashSet<>(); // 避免出现：ConcurrentModificationException
            for (String agentNoItem : allAgentNoList) {
                tempAgentNoSet.addAll(agentInfoService.queryAllSubAgentNo(agentNoItem));
            }
            allAgentNoList.addAll(tempAgentNoSet);

        }

        // 服务商不为空
        if (!ObjUtil.isEmpty(agentNo)) {

            // 查询所有的服务商列表 （ 当前服务商的 直属 服务商  ）
            agentInfoService.list(AgentInfo.gw().select(AgentInfo::getAgentNo).eq(AgentInfo::getPid, agentNo)).forEach(r -> allAgentNoList.add(r.getAgentNo()));

            // 查询所有的商户列表  （ 当前服务商的 直属 商户  ） 【 当前服务商的所属商户 】
            mchInfoService.list(MchInfo.gw().select(MchInfo::getMchNo).eq(MchInfo::getAgentNo, agentNo)).forEach(r -> allMchNoList.add(r.getMchNo()));

            // 查询下级服务商的 子服务商【递归】

            Set<String> tempAgentNoSet = new HashSet<>(); // 避免出现：ConcurrentModificationException
            for (String agentNoItem : allAgentNoList) {
                tempAgentNoSet.addAll(agentInfoService.queryAllSubAgentNo(agentNoItem));
            }
            allAgentNoList.addAll(tempAgentNoSet);

            // 查询下级服务商 所属的商户集合
            for (String agentNoItem : allAgentNoList) {
                mchInfoService.list(MchInfo.gw().select(MchInfo::getMchNo).eq(MchInfo::getAgentNo, agentNoItem)).forEach(r -> allMchNoList.add(r.getMchNo()));
            }

        }

        if (!allMchNoList.isEmpty()) {

            // 查询所有的商户列表
            mchAppService.lambdaQuery().select(MchAppEntity::getAppId).in(MchAppEntity::getMchNo, allMchNoList).list().forEach(r -> allAppIdList.add(r.getAppId()));

        }


        // 服务商：  包括 服务商配置， 下级服务商默认、  服务商商户默认
        for (String agentNoItem : allAgentNoList) {
            for (String wayCode : delWayCodeList) {

                RateConfig r = new RateConfig();
                r.setInfoId(RateConfig.buildInfoId(agentNoItem, RateConfig.AGENTRATE));
                r.setInfoType(CS.SYS_ROLE_TYPE.AGENT);
                r.setIfCode(ifCode);
                r.setWayCode(wayCode);
                result.add(r);

                RateConfig r1 = new RateConfig();
                r1.setInfoId(RateConfig.buildInfoId(agentNoItem, RateConfig.AGENTDEF));
                r1.setInfoType(CS.SYS_ROLE_TYPE.AGENT);
                r1.setIfCode(ifCode);
                r1.setWayCode(wayCode);
                result.add(r1);

                RateConfig r2 = new RateConfig();
                r2.setInfoId(RateConfig.buildInfoId(agentNoItem, RateConfig.MCHAPPLYDEF));
                r2.setInfoType(CS.SYS_ROLE_TYPE.AGENT);
                r2.setIfCode(ifCode);
                r2.setWayCode(wayCode);
                result.add(r2);
            }
        }


        // 商户：  包括 商户应用费率
        for (String appIdItem : allAppIdList) {
            for (String wayCode : delWayCodeList) {

                RateConfig r = new RateConfig();
                r.setInfoId(RateConfig.buildInfoId(appIdItem, RateConfig.MCHRATE));
                r.setInfoType(CS.SYS_ROLE_TYPE.MCH_APP);
                r.setIfCode(ifCode);
                r.setWayCode(wayCode);
                result.add(r);
            }
        }

        return result;
    }

    @GetMapping("/rateInfoDetail")
    public ApiRes rateInfoDetail() {
        String isvNo = getValStringRequired("isvNo");
        String ifCode = getValStringRequired("ifCode");
        Integer range = getValInteger("range");
        String mccCode = getValString("mccCode");
        String infoType = getValStringRequired("infoType");
        String infoId = getValStringRequired("infoId");

        List<RateConfigSimple> result = rateConfigV2Service.getRankFeeList(isvNo, infoType, infoId, ifCode, range, mccCode, isvNo);

        return ApiRes.ok(result);
    }

    @PostMapping("/resetV2")
    public ApiRes resetV2() {
        RateConfigSimple rateConfigSimple = getObject(RateConfigSimple.class);
        rateConfigV2Service.save(rateConfigSimple);

        return ApiRes.ok();
    }
}
