package com.ruoyi.credit.service;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.credit.config.ValidationRuleConfig;
import com.ruoyi.credit.domain.ValidationRule;
import com.ruoyi.credit.service.validator.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import com.fasterxml.jackson.core.JsonProcessingException;

/**
 * 验证规则引擎核心组件 负责管理和执行可配置的验证规则，支持插件化验证器注册和容错处理
 *
 * @author ruoyi
 * @date 2025-12-30
 */
@Component
public class ValidationRuleEngine {

    private static final Logger log = LoggerFactory.getLogger(ValidationRuleEngine.class);

    @Autowired
    private ValidationRuleConfig validationRuleConfig;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private CreditExistenceValidator creditExistenceValidator;

    @Autowired
    private CreditValidityValidator creditValidityValidator;

    @Autowired
    private ContractMatchValidator contractMatchValidator;

    @Autowired
    private AmountConsistencyValidator amountConsistencyValidator;

    @Autowired
    private DateConsistencyValidator dateConsistencyValidator;

    @Autowired
    private StatusValidationValidator statusValidationValidator;

    /**
     * 注册的验证器映射表 Key: 验证器类型，Value: 验证器实例
     */
    private final Map<String, RuleValidator> registeredValidators = new ConcurrentHashMap<>();

    /**
     * 规则执行统计信息
     */
    private final Map<String, RuleExecutionStats> executionStats = new ConcurrentHashMap<>();

    /**
     * 最大重试次数
     */
    private static final int MAX_RETRY_COUNT = 3;

    /**
     * 初始化验证规则引擎
     */
    @PostConstruct
    public void init() {
        log.info("初始化验证规则引擎...");

        // 注册内置验证器
        registerBuiltinValidators();

        log.info("验证规则引擎初始化完成，已注册验证器数量: {}", registeredValidators.size());
    }

    /**
     * 注册内置验证器
     */
    private void registerBuiltinValidators() {
        // 债权凭证存在性验证器
        registerValidator(ValidationRule.TYPE_CREDIT_EXISTENCE, creditExistenceValidator);

        // 债权凭证有效性验证器
        registerValidator(ValidationRule.TYPE_CREDIT_VALIDITY, creditValidityValidator);

        // 合同匹配验证器
        registerValidator(ValidationRule.TYPE_CONTRACT_MATCH, contractMatchValidator);

        // 金额一致性验证器
        registerValidator(ValidationRule.TYPE_AMOUNT_CONSISTENCY, amountConsistencyValidator);

        // 日期一致性验证器
        registerValidator(ValidationRule.TYPE_DATE_CONSISTENCY, dateConsistencyValidator);

        // 状态验证器
        registerValidator(ValidationRule.TYPE_STATUS_VALIDATION, statusValidationValidator);

        log.info("内置验证器注册完成");
    }

    /**
     * 注册验证器
     *
     * @param validatorType 验证器类型
     * @param validator 验证器实例
     */
    public void registerValidator(String validatorType, RuleValidator validator) {
        if (!StringUtils.hasText(validatorType)) {
            throw new IllegalArgumentException("验证器类型不能为空");
        }

        if (validator == null) {
            throw new IllegalArgumentException("验证器实例不能为空");
        }

        registeredValidators.put(validatorType, validator);
        log.info("注册验证器: {} -> {}", validatorType, validator.getClass().getSimpleName());
    }

    /**
     * 注销验证器
     *
     * @param validatorType 验证器类型
     */
    public void unregisterValidator(String validatorType) {
        RuleValidator removed = registeredValidators.remove(validatorType);
        if (removed != null) {
            log.info("注销验证器: {}", validatorType);
        }
    }

    /**
     * 获取已注册的验证器类型列表
     *
     * @return 验证器类型列表
     */
    public Set<String> getRegisteredValidatorTypes() {
        return new HashSet<>(registeredValidators.keySet());
    }

    /**
     * 执行指定规则
     *
     * @param ruleName 规则名称
     * @param context 验证上下文
     * @return 验证结果
     */
    public ValidationResult executeRule(String ruleName, ValidationContext context) {
        if (!StringUtils.hasText(ruleName)) {
            throw new IllegalArgumentException("规则名称不能为空");
        }

        if (context == null) {
            throw new IllegalArgumentException("验证上下文不能为空");
        }

        // 首先尝试通过规则名称获取配置的规则
        ValidationRule rule = validationRuleConfig.getRuleByName(ruleName);

        // 如果没有找到配置的规则，尝试使用内置规则映射
        if (rule == null) {
            rule = createBuiltinRule(ruleName);
        }

        if (rule == null) {
            log.warn("未找到指定的验证规则: {}", ruleName);
            return ValidationResult.failure("未找到指定的验证规则: " + ruleName);
        }

        if (!rule.isActive()) {
            log.debug("规则未激活，跳过执行: {}", ruleName);
            return ValidationResult.skipped("规则未激活: " + ruleName);
        }

        return executeRuleWithRetry(rule, context, 0);
    }

    /**
     * 创建内置规则
     *
     * @param ruleName 规则名称
     * @return 验证规则
     */
    private ValidationRule createBuiltinRule(String ruleName) {
        ValidationRule rule = new ValidationRule();
        rule.setRuleName(ruleName);
        rule.setRuleStatus(ValidationRule.STATUS_ACTIVE);
        rule.setPriority(100);
        rule.setDescription("内置验证规则: " + ruleName);

        // 根据规则名称映射到规则类型
        switch (ruleName) {
            case "credit_existence":
                rule.setRuleType(ValidationRule.TYPE_CREDIT_EXISTENCE);
                break;
            case "credit_validity":
                rule.setRuleType(ValidationRule.TYPE_CREDIT_VALIDITY);
                break;
            case "contract_match":
                rule.setRuleType(ValidationRule.TYPE_CONTRACT_MATCH);
                break;
            case "amount_consistency":
                rule.setRuleType(ValidationRule.TYPE_AMOUNT_CONSISTENCY);
                break;
            case "date_consistency":
                rule.setRuleType(ValidationRule.TYPE_DATE_CONSISTENCY);
                break;
            case "status_validation":
                rule.setRuleType(ValidationRule.TYPE_STATUS_VALIDATION);
                break;
            default:
                log.warn("未知的内置规则名称: {}", ruleName);
                return null;
        }

        return rule;
    }

    /**
     * 执行所有激活的验证规则（按优先级顺序）
     *
     * @param context 验证上下文
     * @return 验证结果列表
     */
    public List<ValidationResult> executeAllRules(ValidationContext context) {
        if (context == null) {
            throw new IllegalArgumentException("验证上下文不能为空");
        }

        List<ValidationRule> activeRules = validationRuleConfig.getActiveRules();
        List<ValidationResult> results = new ArrayList<>();

        log.info("开始执行验证规则，规则数量: {}", activeRules.size());

        for (ValidationRule rule : activeRules) {
            try {
                ValidationResult result = executeRuleWithRetry(rule, context, 0);
                results.add(result);

                // 如果是关键规则失败，可以选择中断后续规则执行
                if (result.isFailed() && isStopOnFailureRule(rule)) {
                    log.warn("关键规则执行失败，中断后续规则执行: {}", rule.getRuleName());
                    break;
                }

            } catch (Exception e) {
                log.error("执行规则时发生未预期异常: {}", rule.getRuleName(), e);
                ValidationResult errorResult = ValidationResult.error(
                        "规则执行异常: " + e.getMessage(), rule.getRuleName());
                results.add(errorResult);

                // 更新统计信息
                updateExecutionStats(rule.getRuleName(), false, System.currentTimeMillis());
            }
        }

        log.info("验证规则执行完成，总结果数量: {}", results.size());
        return results;
    }

    /**
     * 执行指定类型的验证规则
     *
     * @param ruleType 规则类型
     * @param context 验证上下文
     * @return 验证结果列表
     */
    public List<ValidationResult> executeRulesByType(String ruleType, ValidationContext context) {
        if (!StringUtils.hasText(ruleType)) {
            throw new IllegalArgumentException("规则类型不能为空");
        }

        if (context == null) {
            throw new IllegalArgumentException("验证上下文不能为空");
        }

        List<ValidationRule> rules = validationRuleConfig.getRulesByType(ruleType);
        List<ValidationResult> results = new ArrayList<>();

        // 按优先级排序
        rules.sort(Comparator.comparing(ValidationRule::getPriority));

        log.info("开始执行指定类型的验证规则: {}，规则数量: {}", ruleType, rules.size());

        for (ValidationRule rule : rules) {
            if (rule.isActive()) {
                try {
                    ValidationResult result = executeRuleWithRetry(rule, context, 0);
                    results.add(result);
                } catch (Exception e) {
                    log.error("执行规则时发生异常: {}", rule.getRuleName(), e);
                    ValidationResult errorResult = ValidationResult.error(
                            "规则执行异常: " + e.getMessage(), rule.getRuleName());
                    results.add(errorResult);
                }
            }
        }

        return results;
    }

    /**
     * 带重试机制的规则执行
     *
     * @param rule 验证规则
     * @param context 验证上下文
     * @param retryCount 当前重试次数
     * @return 验证结果
     */
    private ValidationResult executeRuleWithRetry(ValidationRule rule, ValidationContext context, int retryCount) {
        long startTime = System.currentTimeMillis();

        try {
            log.debug("执行验证规则: {} (优先级: {}, 重试次数: {})",
                    rule.getRuleName(), rule.getPriority(), retryCount);

            // 获取对应的验证器
            RuleValidator validator = registeredValidators.get(rule.getRuleType());
            if (validator == null) {
                String message = "未找到对应的验证器: " + rule.getRuleType();
                log.error(message);
                return ValidationResult.failure(message);
            }

            // 解析规则配置
            RuleConfig ruleConfig = parseRuleConfig(rule);

            // 执行验证
            ValidationResult result = executeWithTimeout(validator, rule, ruleConfig, context);

            // 更新统计信息
            long executionTime = System.currentTimeMillis() - startTime;
            updateExecutionStats(rule.getRuleName(), result.isSuccess(), executionTime);

            log.debug("规则执行完成: {}, 结果: {}, 耗时: {}ms",
                    rule.getRuleName(), result.getStatus(), executionTime);

            return result;

        } catch (Exception e) {
            long executionTime = System.currentTimeMillis() - startTime;
            log.error("规则执行失败: {}, 耗时: {}ms", rule.getRuleName(), executionTime, e);

            // 如果还有重试机会且是可重试的异常，则进行重试
            if (retryCount < MAX_RETRY_COUNT && isRetryableException(e)) {
                log.info("规则执行失败，准备重试: {} (第{}次重试)", rule.getRuleName(), retryCount + 1);

                // 指数退避延迟
                try {
                    Thread.sleep(calculateRetryDelay(retryCount));
                } catch (InterruptedException ie) {
                    Thread.currentThread().interrupt();
                    return ValidationResult.error("规则执行被中断: " + ie.getMessage(), rule.getRuleName());
                }

                return executeRuleWithRetry(rule, context, retryCount + 1);
            }

            // 更新统计信息
            updateExecutionStats(rule.getRuleName(), false, executionTime);

            return ValidationResult.error("规则执行失败: " + e.getMessage(), rule.getRuleName());
        }
    }

    /**
     * 带超时控制的规则执行
     *
     * @param validator 验证器
     * @param rule 验证规则
     * @param ruleConfig 规则配置
     * @param context 验证上下文
     * @return 验证结果
     */
    private ValidationResult executeWithTimeout(RuleValidator validator, ValidationRule rule,
            RuleConfig ruleConfig, ValidationContext context) {
        // 这里可以使用CompletableFuture或其他机制实现超时控制
        // 为了简化实现，暂时直接调用验证器
        return validator.validate(rule, ruleConfig, context);
    }

    /**
     * 解析规则配置
     *
     * @param rule 验证规则
     * @return 规则配置对象
     */
    private RuleConfig parseRuleConfig(ValidationRule rule) {
        try {
            if (StringUtils.hasText(rule.getConfigJson())) {
                return objectMapper.readValue(rule.getConfigJson(), RuleConfig.class);
            } else {
                return new RuleConfig();
            }
        } catch (JsonProcessingException e) {
            log.warn("解析规则配置失败，使用默认配置: {}", rule.getRuleName(), e);
            return new RuleConfig();
        }
    }

    /**
     * 判断是否为可重试的异常
     *
     * @param exception 异常
     * @return 是否可重试
     */
    private boolean isRetryableException(Exception exception) {
        if (exception == null) {
            return false;
        }

        // 网络异常、超时异常等可以重试
        return exception instanceof java.net.SocketTimeoutException
                || exception instanceof java.net.ConnectException
                || exception instanceof java.sql.SQLException
                || (exception.getMessage() != null
                && (exception.getMessage().contains("timeout")
                || exception.getMessage().contains("connection")));
    }

    /**
     * 计算重试延迟时间（指数退避）
     *
     * @param retryCount 重试次数
     * @return 延迟时间（毫秒）
     */
    private long calculateRetryDelay(int retryCount) {
        return Math.min(1000L * (1L << retryCount), 10000L); // 最大延迟10秒
    }

    /**
     * 判断是否为失败时停止执行的规则
     *
     * @param rule 验证规则
     * @return 是否停止执行
     */
    private boolean isStopOnFailureRule(ValidationRule rule) {
        try {
            RuleConfig config = parseRuleConfig(rule);
            return config.isStopOnFailure();
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 更新规则执行统计信息
     *
     * @param ruleName 规则名称
     * @param success 是否成功
     * @param executionTime 执行时间
     */
    private void updateExecutionStats(String ruleName, boolean success, long executionTime) {
        executionStats.compute(ruleName, (key, stats) -> {
            if (stats == null) {
                stats = new RuleExecutionStats(ruleName);
            }
            stats.recordExecution(success, executionTime);
            return stats;
        });
    }

    /**
     * 获取规则执行统计信息
     *
     * @param ruleName 规则名称
     * @return 统计信息
     */
    public RuleExecutionStats getExecutionStats(String ruleName) {
        return executionStats.get(ruleName);
    }

    /**
     * 获取所有规则的执行统计信息
     *
     * @return 统计信息映射表
     */
    public Map<String, RuleExecutionStats> getAllExecutionStats() {
        return new HashMap<>(executionStats);
    }

    /**
     * 清空执行统计信息
     */
    public void clearExecutionStats() {
        executionStats.clear();
        log.info("已清空规则执行统计信息");
    }

    /**
     * 验证规则引擎健康检查
     *
     * @return 健康检查结果
     */
    public EngineHealthStatus healthCheck() {
        EngineHealthStatus status = new EngineHealthStatus();

        try {
            // 检查配置是否正常加载
            List<ValidationRule> activeRules = validationRuleConfig.getActiveRules();
            status.setActiveRulesCount(activeRules.size());

            // 检查验证器注册情况
            status.setRegisteredValidatorsCount(registeredValidators.size());

            // 检查是否有执行失败率过高的规则
            long totalExecutions = 0;
            long totalFailures = 0;

            for (RuleExecutionStats stats : executionStats.values()) {
                totalExecutions += stats.getTotalExecutions();
                totalFailures += stats.getFailureCount();
            }

            if (totalExecutions > 0) {
                double failureRate = (double) totalFailures / totalExecutions;
                status.setOverallFailureRate(failureRate);
                status.setHealthy(failureRate < 0.1); // 失败率低于10%认为健康
            } else {
                status.setHealthy(true);
            }

            status.setLastCheckTime(new Date());

        } catch (Exception e) {
            log.error("验证规则引擎健康检查失败", e);
            status.setHealthy(false);
            status.setErrorMessage(e.getMessage());
        }

        return status;
    }
}
