package com.ruoyi.ccdi.project.service.impl;

import com.ruoyi.ccdi.project.domain.CcdiModelParam;
import com.ruoyi.ccdi.project.domain.CcdiProject;
import com.ruoyi.ccdi.project.domain.entity.CcdiBankTagRule;
import com.ruoyi.ccdi.project.domain.vo.BankTagRuleExecutionConfig;
import com.ruoyi.ccdi.project.mapper.CcdiModelParamMapper;
import com.ruoyi.ccdi.project.mapper.CcdiProjectMapper;
import com.ruoyi.common.exception.ServiceException;
import org.springframework.stereotype.Component;

import jakarta.annotation.Resource;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;

/**
 * 流水标签规则执行参数解析器
 */
@Slf4j
@Component
public class BankTagRuleConfigResolver {

    private static final Map<String, Set<String>> RULE_PARAM_MAPPING = Map.ofEntries(
        Map.entry("SINGLE_LARGE_INCOME", Set.of("SINGLE_TRANSACTION_AMOUNT")),
        Map.entry("CUMULATIVE_INCOME", Set.of("CUMULATIVE_TRANSACTION_AMOUNT")),
        Map.entry("EXTERNAL_CUMULATIVE_TRANSACTION_AMOUNT", Set.of("CUMULATIVE_TRANSACTION_AMOUNT")),
        Map.entry("ANNUAL_TURNOVER", Set.of("ANNUAL_TURNOVER")),
        Map.entry("EXTERNAL_ANNUAL_TURNOVER", Set.of("ANNUAL_TURNOVER")),
        Map.entry("LARGE_CASH_DEPOSIT", Set.of("LARGE_CASH_DEPOSIT")),
        Map.entry("FREQUENT_CASH_DEPOSIT", Set.of("LARGE_CASH_DEPOSIT", "FREQUENT_CASH_DEPOSIT")),
        Map.entry("LARGE_TRANSFER", Set.of("FREQUENT_TRANSFER")),
        Map.entry("EXTERNAL_SINGLE_LARGE_AMOUNT", Set.of("FREQUENT_TRANSFER")),
        Map.entry("FOREX_BUY_AMT", Set.of("SINGLE_PURCHASE_AMOUNT")),
        Map.entry("FOREX_SELL_AMT", Set.of("SINGLE_SETTLEMENT_AMOUNT")),
        Map.entry("WITHDRAW_CNT", Set.of("WITHDRAW_CNT")),
        Map.entry("WITHDRAW_AMT", Set.of("WITHDRAW_AMT")),
        Map.entry("STOCK_TFR_LARGE", Set.of("STOCK_TFR_LARGE")),
        Map.entry("LARGE_STOCK_TRADING", Set.of("STOCK_TFR_LARGE")),
        Map.entry("MULTI_PARTY_GAMBLING_TRANSFER", Set.of("MULTI_PARTY_AMT_MIN", "MULTI_PARTY_AMT_MAX")),
        Map.entry("EXTERNAL_MULTI_PARTY_GAMBLING_TRANSFER", Set.of("MULTI_PARTY_AMT_MIN", "MULTI_PARTY_AMT_MAX")),
        Map.entry("MONTHLY_FIXED_INCOME", Set.of("MONTHLY_FIXED_INCOME")),
        Map.entry("FIXED_COUNTERPARTY_TRANSFER", Set.of("FIXED_COUNTERPARTY_TRANSFER_MIN", "FIXED_COUNTERPARTY_TRANSFER_MAX"))
    );

    private static final Map<String, String> RULE_PARAM_MODEL_MAPPING = Map.of(
        "EXTERNAL_SINGLE_LARGE_AMOUNT", "LARGE_TRANSACTION",
        "EXTERNAL_CUMULATIVE_TRANSACTION_AMOUNT", "LARGE_TRANSACTION",
        "EXTERNAL_ANNUAL_TURNOVER", "LARGE_TRANSACTION",
        "EXTERNAL_MULTI_PARTY_GAMBLING_TRANSFER", "SUSPICIOUS_GAMBLING"
    );

    @Resource
    private CcdiProjectMapper projectMapper;

    @Resource
    private CcdiModelParamMapper modelParamMapper;

    /**
     * 解析规则执行配置
     *
     * @param projectId 项目ID
     * @param ruleMeta 规则元数据
     * @return 执行配置
     */
    public BankTagRuleExecutionConfig resolve(Long projectId, CcdiBankTagRule ruleMeta) {
        if (projectId == null) {
            throw new ServiceException("项目ID不能为空");
        }
        if (ruleMeta == null) {
            throw new ServiceException("规则信息不能为空");
        }

        CcdiProject project = projectMapper.selectById(projectId);
        if (project == null) {
            throw new ServiceException("项目不存在");
        }

        Long effectiveProjectId = "default".equals(project.getConfigType()) ? 0L : projectId;
        String paramModelCode = RULE_PARAM_MODEL_MAPPING.getOrDefault(ruleMeta.getRuleCode(), ruleMeta.getModelCode());
        List<CcdiModelParam> params = modelParamMapper.selectByProjectAndModel(effectiveProjectId, paramModelCode);

        Map<String, String> thresholdValues = new LinkedHashMap<>();
        Set<String> requiredParamCodes = RULE_PARAM_MAPPING.getOrDefault(ruleMeta.getRuleCode(), Set.of());
        log.info("【流水标签】解析规则参数: projectId={}, effectiveProjectId={}, ruleCode={}, paramModelCode={}, requiredParams={}",
            projectId, effectiveProjectId, ruleMeta.getRuleCode(), paramModelCode, requiredParamCodes);
        for (CcdiModelParam param : params) {
            if (requiredParamCodes.contains(param.getParamCode())) {
                thresholdValues.put(param.getParamCode(), param.getParamValue());
            }
        }
        log.debug("【流水标签】规则参数解析结果: projectId={}, ruleCode={}, thresholdValues={}",
            projectId, ruleMeta.getRuleCode(), thresholdValues);

        Set<String> missingParamCodes = requiredParamCodes.stream()
            .filter(code -> !thresholdValues.containsKey(code))
            .collect(Collectors.toSet());
        if (!missingParamCodes.isEmpty()) {
            log.warn("【流水标签】规则参数缺失: projectId={}, ruleCode={}, missingParams={}",
                projectId, ruleMeta.getRuleCode(), missingParamCodes);
        }

        BankTagRuleExecutionConfig config = new BankTagRuleExecutionConfig();
        config.setProjectId(projectId);
        config.setEffectiveProjectId(effectiveProjectId);
        config.setRuleMeta(ruleMeta);
        config.setThresholdValues(thresholdValues);
        return config;
    }
}
