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

import cn.hutool.core.collection.CollUtil;
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.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jeequan.jeepay.core.aop.MethodLog;
import com.jeequan.jeepay.core.constants.CS;
import com.jeequan.jeepay.core.model.ApiRes;
import com.jeequan.jeepay.core.model.applyment.PaywayFee;
import com.jeequan.jeepay.db.entity.MchAppEntity;
import com.jeequan.jeepay.db.entity.MchInfo;
import com.jeequan.jeepay.db.entity.PayWay;
import com.jeequan.jeepay.db.entity.RateConfig;
import com.jeequan.jeepay.mch.ctrl.CommonCtrl;
import com.jeequan.jeepay.model.RateConfigSimple;
import com.jeequan.jeepay.service.impl.*;
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 MchInfoService mchInfoService;
    @Autowired
    private RateConfigService rateConfigService;
    @Autowired
    private PayWayService payWayService;
    @Autowired
    private MchAppService mchAppService;
    @Autowired
    private RateConfigV2Service rateConfigV2Service;

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

        String ifCode = getValStringRequired("ifCode"); // ifCode
        String infoId = getValStringRequired("infoId"); // infoId
        String isvNo = getValStringRequired("isvNo"); // infoId
        String configMode = getValStringRequired("configMode"); // 设置类型
        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();
        }

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

        // 是否仅显示 支持进件的支付方式（用作进件使用）
        boolean isOnlyApplymentSupport = false;


        MchInfo mchInfo = mchInfoService.getById(getCurrentMchNo());

        belongAgentNo = mchInfo.getAgentNo();

        // 商户进件模式
        if (RateConfig.CONFIG_MODE_MCHAPPLYMENT.equals(configMode)) {
            isOnlyApplymentSupport = true;
        }

        IPage<PayWay> pages = payWayService.queryWayListByRate(ifCode, isvNo, belongAgentNo, isOnlyApplymentSupport, range, mccCode, isvNo);

        if (pages.getRecords().isEmpty()) {
            return ApiRes.page(pages);
        }

        // 进件模式 : 只能获取到默认进件费率。
        if (isOnlyApplymentSupport && mchInfo.getType() == CS.MCH_TYPE_ISVSUB) {

            Set<String> defWayCodes;

            if (!ObjUtil.isEmpty(mchInfo.getAgentNo())) { // 包含上级服务商

                // 上级服务商支持的 支付方式 [默认支付方式]
                defWayCodes = rateConfigService.getAllWayCodesByInfoId(ifCode, RateConfig.appendInfoByMchDef(mchInfo.getAgentNo()), CS.SYS_ROLE_TYPE.AGENT, isvNo);

            } else { // 顶级商户

                // 服务商支持的 支付方式 [默认支付方式]
                defWayCodes = rateConfigService.getAllWayCodesByInfoId(ifCode, RateConfig.appendInfoByMchDef(isvNo), CS.SYS_ROLE_TYPE.ISV, isvNo);
            }

            List<PayWay> result = new ArrayList<>();
            for (PayWay item : pages.getRecords()) {
                if (defWayCodes.contains(item.getWayCode())) {
                    result.add(item);
                }
            }

            return ApiRes.page(new Page<PayWay>().setRecords(result).setTotal(result.size()));
        }

        return ApiRes.page(pages);
    }


    /**
     * 查询当前已经配置的列表
     **/
    @GetMapping(value = "/savedMapData")
    public ApiRes savedMapData() {

        String ifCode = getValStringRequired("ifCode"); // ifCode
        String infoId = getValStringRequired("infoId"); // infoId
        String configMode = getValStringRequired("configMode"); // 设置类型
        Integer range = getValInteger("range");
        String mccCode = getValString("mccCode");
        String isvNo = getValString("isvNo");

        /* 获取商户费率时, 通过关联的应用获取费率类型 */
        String mchAppId = getValString("appId");
        if (!ObjUtil.isEmpty(mchAppId)) {
            MchAppEntity mchApp = mchAppService.getById(mchAppId);
            range = mchApp.getRange();
            mccCode = mchApp.getMccCode();
        }

        // 商户自主进件
        if (RateConfig.CONFIG_MODE_MCHAPPLYMENT.equals(configMode)) {
            Map<String, Object> result = new HashMap<>();

            String mchNo = getCurrentMchNo();

            Map<String, PaywayFee> paywayFeeMap = new HashMap<>();

            Map<String, PaywayFee> mchSetFeeMap = new HashMap<>();

            // 查询默认费率
            MchInfo mchInfo = mchInfoService.getById(mchNo);
            // 特约商户
            if (mchInfo.getType() == CS.MCH_TYPE_ISVSUB) {
                // 先获取代理给商户配置的特定费率
                mchSetFeeMap = rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByMchApp(mchInfo.getMchNo()), CS.SYS_ROLE_TYPE.MCH_APP, ifCode, range, mccCode, isvNo);

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

            if (mchSetFeeMap == null) {
                mchSetFeeMap = new HashMap<>();
            }

            // 查询已经配置的费率
            String applyId = infoId.split("_")[0];
            if (!ObjUtil.isEmpty(applyId)) {
                // 已经配置的费率
//                Map<String, PaywayFee> paywayFeeMapByApplyment = rateConfigService.queryPaywayFeeMapByApplyment(applyId);
                // 此处费率不从商户信息里面取了
                Map<String, PaywayFee> applymentPaywayFee = rateConfigService.queryPaywayFeeMap(mchNo, CS.SYS_ROLE_TYPE.MCH_APPLYMENT, ifCode, range, mccCode, isvNo);

                // 同时收集两个数据的keySet作为并集
                Set<String> keySet = mchSetFeeMap.keySet();
                keySet.addAll(applymentPaywayFee.keySet());

                // 当进件关闭该支付产品时， 那么需要读取默认费率（避免全部关闭后保存， 再次进入无法保存的问题。）
                for (String key : keySet) {
                    if (applymentPaywayFee.get(key) != null) {
                        paywayFeeMap.put(key, applymentPaywayFee.get(key));
                    } else {
                        paywayFeeMap.put(key, mchSetFeeMap.get(key));
                    }
                }
            } else {
                paywayFeeMap.putAll(mchSetFeeMap);
            }

            if (!CollUtil.isEmpty(paywayFeeMap)) {
                result.put(RateConfig.MCHRATE, paywayFeeMap);
            }

            return ApiRes.ok(result);
        }

        // 普通商户的费率配置
        if (RateConfig.CONFIG_MODE_MCHSELFAPP1.equals(configMode)) {
            Map<String, Object> result = new HashMap<>();
            result.put(RateConfig.MCHRATE, rateConfigService.queryPaywayFeeMap(RateConfig.appendInfoByMchApp(infoId), commonGetInfoType(configMode), ifCode, range, mccCode, isvNo));
            return ApiRes.ok(result);
        }


        return ApiRes.ok();
    }

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

        String configMode = getValStringRequired("configMode");

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

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

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

        // 商户费率 (只能是普通商户)
        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)));
        }

        LambdaQueryWrapper<RateConfig> delWrapper = RateConfig.gw();
        delWrapper.eq(RateConfig::getIfCode, mainRateConfig.getIfCode());
        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, false, null);
        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;

        } else if (RateConfig.CONFIG_MODE_MCHSELFAPP1.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.MCHAPPLYDEF),
                    (infoId + "_" + RateConfig.MCHAPPLYMAX)
            );

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

            return Arrays.asList(
                    (infoId + "_" + RateConfig.AGENTRATE),
                    (infoId + "_" + RateConfig.AGENTDEF),
                    (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)
            );

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

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

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

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

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

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

        }

        return new ArrayList<>();
    }

    @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);
    }
}
