package com.qaup.collision.rule.service;

import com.qaup.collision.common.model.MovingObject.MovingObjectType;
import com.qaup.collision.rule.model.entity.SpatialRule;
import com.qaup.collision.rule.model.enums.RuleCategory;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;

/**
 * 规则优先级排序服务接口
 * 负责处理多个规则同时适用时的优先级逻辑和排序
 * 
 * @author AI Assistant
 * @version 1.0
 * @since 2025-01-17
 */
public interface RulePriorityService {

    /**
     * 对规则列表按优先级排序
     * @param rules 规则列表
     * @return 按优先级排序的规则列表（优先级高的在前）
     */
    List<SpatialRule> sortRulesByPriority(List<SpatialRule> rules);

    /**
     * 对规则列表按优先级排序（考虑车辆类型）
     * @param rules 规则列表
     * @param vehicleType 车辆类型
     * @return 按优先级排序的规则列表
     */
    List<SpatialRule> sortRulesByPriority(List<SpatialRule> rules, MovingObjectType vehicleType);

    /**
     * 对规则列表按优先级排序（考虑时间因素）
     * @param rules 规则列表
     * @param timestamp 时间戳
     * @return 按优先级排序的规则列表
     */
    List<SpatialRule> sortRulesByPriority(List<SpatialRule> rules, LocalDateTime timestamp);

    /**
     * 对规则列表按优先级排序（考虑车辆类型和时间）
     * @param rules 规则列表
     * @param vehicleType 车辆类型
     * @param timestamp 时间戳
     * @return 按优先级排序的规则列表
     */
    List<SpatialRule> sortRulesByPriority(List<SpatialRule> rules, MovingObjectType vehicleType, LocalDateTime timestamp);

    /**
     * 按规则类别分组并排序
     * @param rules 规则列表
     * @return 按类别分组的规则Map，每组内部按优先级排序
     */
    Map<RuleCategory, List<SpatialRule>> groupAndSortByCategory(List<SpatialRule> rules);

    /**
     * 获取最高优先级的规则
     * @param rules 规则列表
     * @return 最高优先级的规则，如果列表为空返回null
     */
    SpatialRule getHighestPriorityRule(List<SpatialRule> rules);

    /**
     * 获取指定类别中最高优先级的规则
     * @param rules 规则列表
     * @param category 规则类别
     * @return 指定类别中最高优先级的规则，如果没有找到返回null
     */
    SpatialRule getHighestPriorityRuleByCategory(List<SpatialRule> rules, RuleCategory category);

    /**
     * 过滤出指定优先级范围的规则
     * @param rules 规则列表
     * @param minPriority 最小优先级（包含）
     * @param maxPriority 最大优先级（包含）
     * @return 过滤后的规则列表
     */
    List<SpatialRule> filterRulesByPriorityRange(List<SpatialRule> rules, int minPriority, int maxPriority);

    /**
     * 过滤出高优先级规则（优先级小于指定值）
     * @param rules 规则列表
     * @param priorityThreshold 优先级阈值
     * @return 高优先级规则列表
     */
    List<SpatialRule> filterHighPriorityRules(List<SpatialRule> rules, int priorityThreshold);

    /**
     * 解决规则冲突（当多个规则有相同优先级时）
     * @param conflictingRules 冲突的规则列表
     * @param vehicleType 车辆类型
     * @param timestamp 时间戳
     * @return 解决冲突后的规则列表
     */
    List<SpatialRule> resolveRuleConflicts(List<SpatialRule> conflictingRules, MovingObjectType vehicleType, LocalDateTime timestamp);

    /**
     * 检查规则列表中是否有优先级冲突
     * @param rules 规则列表
     * @return 如果存在优先级冲突返回true
     */
    boolean hasPriorityConflicts(List<SpatialRule> rules);

    /**
     * 获取规则的有效优先级（考虑动态因素）
     * @param rule 规则
     * @param vehicleType 车辆类型
     * @param timestamp 时间戳
     * @return 有效优先级值
     */
    int getEffectivePriority(SpatialRule rule, MovingObjectType vehicleType, LocalDateTime timestamp);

    /**
     * 获取规则类别的默认优先级
     * @param category 规则类别
     * @return 默认优先级值
     */
    int getCategoryDefaultPriority(RuleCategory category);

    /**
     * 计算规则的紧急程度分数
     * @param rule 规则
     * @param vehicleType 车辆类型
     * @param timestamp 时间戳
     * @return 紧急程度分数（分数越高越紧急）
     */
    double calculateUrgencyScore(SpatialRule rule, MovingObjectType vehicleType, LocalDateTime timestamp);

    /**
     * 按紧急程度排序规则
     * @param rules 规则列表
     * @param vehicleType 车辆类型
     * @param timestamp 时间戳
     * @return 按紧急程度排序的规则列表（紧急的在前）
     */
    List<SpatialRule> sortRulesByUrgency(List<SpatialRule> rules, MovingObjectType vehicleType, LocalDateTime timestamp);

    /**
     * 获取优先级统计信息
     * @param rules 规则列表
     * @return 优先级统计信息
     */
    PriorityStatistics getPriorityStatistics(List<SpatialRule> rules);

    /**
     * 验证规则优先级配置
     * @param rules 规则列表
     * @return 验证结果
     */
    PriorityValidationResult validatePriorityConfiguration(List<SpatialRule> rules);

    /**
     * 优先级统计信息类
     */
    class PriorityStatistics {
        private final int totalRules;
        private final int minPriority;
        private final int maxPriority;
        private final double avgPriority;
        private final Map<Integer, Long> priorityDistribution;
        private final Map<RuleCategory, Integer> categoryAveragePriorities;
        private final int conflictingRulesCount;

        public PriorityStatistics(int totalRules, int minPriority, int maxPriority, double avgPriority,
                                 Map<Integer, Long> priorityDistribution, Map<RuleCategory, Integer> categoryAveragePriorities,
                                 int conflictingRulesCount) {
            this.totalRules = totalRules;
            this.minPriority = minPriority;
            this.maxPriority = maxPriority;
            this.avgPriority = avgPriority;
            this.priorityDistribution = priorityDistribution;
            this.categoryAveragePriorities = categoryAveragePriorities;
            this.conflictingRulesCount = conflictingRulesCount;
        }

        public int getTotalRules() { return totalRules; }
        public int getMinPriority() { return minPriority; }
        public int getMaxPriority() { return maxPriority; }
        public double getAvgPriority() { return avgPriority; }
        public Map<Integer, Long> getPriorityDistribution() { return priorityDistribution; }
        public Map<RuleCategory, Integer> getCategoryAveragePriorities() { return categoryAveragePriorities; }
        public int getConflictingRulesCount() { return conflictingRulesCount; }

        public boolean hasConflicts() {
            return conflictingRulesCount > 0;
        }

        public int getPriorityRange() {
            return maxPriority - minPriority;
        }

        @Override
        public String toString() {
            return String.format("PriorityStatistics{totalRules=%d, minPriority=%d, maxPriority=%d, avgPriority=%.2f, conflicts=%d}",
                               totalRules, minPriority, maxPriority, avgPriority, conflictingRulesCount);
        }
    }

    /**
     * 优先级验证结果类
     */
    class PriorityValidationResult {
        private final boolean valid;
        private final List<String> errors;
        private final List<String> warnings;
        private final List<String> recommendations;
        private final List<RuleConflict> conflicts;

        public PriorityValidationResult(boolean valid, List<String> errors, List<String> warnings,
                                       List<String> recommendations, List<RuleConflict> conflicts) {
            this.valid = valid;
            this.errors = errors;
            this.warnings = warnings;
            this.recommendations = recommendations;
            this.conflicts = conflicts;
        }

        public boolean isValid() { return valid; }
        public List<String> getErrors() { return errors; }
        public List<String> getWarnings() { return warnings; }
        public List<String> getRecommendations() { return recommendations; }
        public List<RuleConflict> getConflicts() { return conflicts; }

        public boolean hasIssues() {
            return !errors.isEmpty() || !warnings.isEmpty() || !conflicts.isEmpty();
        }

        @Override
        public String toString() {
            return String.format("PriorityValidationResult{valid=%s, errors=%d, warnings=%d, conflicts=%d}",
                               valid, errors.size(), warnings.size(), conflicts.size());
        }
    }

    /**
     * 规则冲突信息类
     */
    class RuleConflict {
        private final List<SpatialRule> conflictingRules;
        private final String conflictType;
        private final String description;
        private final int severity; // 1-10，10为最严重

        public RuleConflict(List<SpatialRule> conflictingRules, String conflictType, String description, int severity) {
            this.conflictingRules = conflictingRules;
            this.conflictType = conflictType;
            this.description = description;
            this.severity = severity;
        }

        public List<SpatialRule> getConflictingRules() { return conflictingRules; }
        public String getConflictType() { return conflictType; }
        public String getDescription() { return description; }
        public int getSeverity() { return severity; }

        public boolean isHighSeverity() {
            return severity >= 7;
        }

        public boolean isCritical() {
            return severity >= 9;
        }

        @Override
        public String toString() {
            return String.format("RuleConflict{type=%s, severity=%d, rulesCount=%d, description=%s}",
                               conflictType, severity, conflictingRules.size(), description);
        }
    }
} 