package com.qaup.collision.rule.service.impl;

import com.qaup.collision.common.model.MovingObject;
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 com.qaup.collision.rule.service.RulePriorityService;
import com.qaup.collision.rule.service.VehicleTypePermissionService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 规则优先级排序服务实现类
 * 负责处理多个规则同时适用时的优先级逻辑和排序
 * 
 * @author AI Assistant
 * @version 1.0
 * @since 2025-01-17
 */
@Service
public class RulePriorityServiceImpl implements RulePriorityService {

    private static final Logger logger = LoggerFactory.getLogger(RulePriorityServiceImpl.class);

    @Autowired
    private VehicleTypePermissionService vehicleTypePermissionService;

    // 规则类别默认优先级映射（数值越小优先级越高）
    private static final Map<RuleCategory, Integer> CATEGORY_DEFAULT_PRIORITIES = Map.of(
        RuleCategory.SAFETY_ZONE, 1,        // 最高优先级：安全区域
        RuleCategory.ACCESS_CONTROL, 2,     // 高优先级：准入控制
        RuleCategory.PRIORITY_CONTROL, 3,   // 中高优先级：优先级控制
        RuleCategory.SPEED_LIMIT, 4,        // 中等优先级：限速
        RuleCategory.VEHICLE_RESTRICTION, 5, // 中等优先级：车辆限制
        RuleCategory.HEIGHT_LIMIT, 6,       // 中低优先级：限高
        RuleCategory.WEIGHT_LIMIT, 7,       // 中低优先级：限重
        RuleCategory.TIME_RESTRICTION, 8,   // 低优先级：时间限制
        RuleCategory.CUSTOM, 9         // 最低优先级：自定义规则
    );

    // 紧急情况下的优先级调整因子
    private static final Map<RuleCategory, Double> URGENCY_FACTORS = Map.of(
        RuleCategory.SAFETY_ZONE, 2.0,        // 安全区域紧急时优先级翻倍
        RuleCategory.ACCESS_CONTROL, 1.8,     // 准入控制高紧急系数
        RuleCategory.PRIORITY_CONTROL, 1.5,   // 优先级控制中等紧急系数
        RuleCategory.SPEED_LIMIT, 1.3,        // 限速中等紧急系数
        RuleCategory.VEHICLE_RESTRICTION, 1.2, // 车辆限制低紧急系数
        RuleCategory.HEIGHT_LIMIT, 1.1,       // 限高低紧急系数
        RuleCategory.WEIGHT_LIMIT, 1.1,       // 限重低紧急系数
        RuleCategory.TIME_RESTRICTION, 1.0,   // 时间限制无紧急调整
        RuleCategory.CUSTOM, 1.0         // 自定义规则无紧急调整
    );

    @Override
    public List<SpatialRule> sortRulesByPriority(List<SpatialRule> rules) {
        if (rules == null || rules.isEmpty()) {
            return new ArrayList<>();
        }

        try {
            return rules.stream()
                    .sorted(Comparator
                            .comparing(SpatialRule::getPriority) // 首先按配置的优先级排序
                            .thenComparing(rule -> getCategoryDefaultPriority(rule.getCategory())) // 然后按类别默认优先级
                            .thenComparing(SpatialRule::getRuleId)) // 最后按ID排序保证稳定性
                    .collect(Collectors.toList());

        } catch (Exception e) {
            logger.error("规则优先级排序失败", e);
            return new ArrayList<>(rules); // 出错时返回原列表
        }
    }

    @Override
    public List<SpatialRule> sortRulesByPriority(List<SpatialRule> rules, MovingObjectType vehicleType) {
        if (rules == null || rules.isEmpty()) {
            return new ArrayList<>();
        }

        try {
            // 根据车辆类型调整优先级
            return rules.stream()
                    .sorted(Comparator
                            .comparing((SpatialRule rule) -> getEffectivePriority(rule, vehicleType, LocalDateTime.now()))
                            .thenComparing(SpatialRule::getRuleId))
                    .collect(Collectors.toList());

        } catch (Exception e) {
            logger.error("按车辆类型排序规则失败: vehicleType={}", vehicleType, e);
            return sortRulesByPriority(rules); // 降级到基本排序
        }
    }

    @Override
    public List<SpatialRule> sortRulesByPriority(List<SpatialRule> rules, LocalDateTime timestamp) {
        return sortRulesByPriority(rules); // 基本实现
    }

    @Override
    public List<SpatialRule> sortRulesByPriority(List<SpatialRule> rules, MovingObjectType vehicleType, LocalDateTime timestamp) {
        return sortRulesByPriority(rules, vehicleType); // 基本实现
    }

    @Override
    public Map<RuleCategory, List<SpatialRule>> groupAndSortByCategory(List<SpatialRule> rules) {
        if (rules == null || rules.isEmpty()) {
            return new HashMap<>();
        }

        try {
            return rules.stream()
                    .collect(Collectors.groupingBy(
                            SpatialRule::getCategory,
                            LinkedHashMap::new, // 保持插入顺序
                            Collectors.collectingAndThen(
                                    Collectors.toList(),
                                    this::sortRulesByPriority
                            )
                    ));

        } catch (Exception e) {
            logger.error("按类别分组排序失败", e);
            return new HashMap<>();
        }
    }

    @Override
    public SpatialRule getHighestPriorityRule(List<SpatialRule> rules) {
        if (rules == null || rules.isEmpty()) {
            return null;
        }

        try {
            return sortRulesByPriority(rules).get(0);

        } catch (Exception e) {
            logger.error("获取最高优先级规则失败", e);
            return null;
        }
    }

    @Override
    public SpatialRule getHighestPriorityRuleByCategory(List<SpatialRule> rules, RuleCategory category) {
        if (rules == null || rules.isEmpty()) {
            return null;
        }

        try {
            return rules.stream()
                    .filter(rule -> rule.getCategory() == category)
                    .min(Comparator.comparing(SpatialRule::getPriority))
                    .orElse(null);

        } catch (Exception e) {
            logger.error("获取类别最高优先级规则失败: category={}", category, e);
            return null;
        }
    }

    @Override
    public List<SpatialRule> filterRulesByPriorityRange(List<SpatialRule> rules, int minPriority, int maxPriority) {
        if (rules == null || rules.isEmpty()) {
            return new ArrayList<>();
        }

        try {
            return rules.stream()
                    .filter(rule -> {
                        int priority = rule.getPriority();
                        return priority >= minPriority && priority <= maxPriority;
                    })
                    .collect(Collectors.toList());

        } catch (Exception e) {
            logger.error("按优先级范围过滤失败: min={}, max={}", minPriority, maxPriority, e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<SpatialRule> filterHighPriorityRules(List<SpatialRule> rules, int priorityThreshold) {
        if (rules == null || rules.isEmpty()) {
            return new ArrayList<>();
        }

        try {
            return rules.stream()
                    .filter(rule -> rule.getPriority() < priorityThreshold)
                    .collect(Collectors.toList());

        } catch (Exception e) {
            logger.error("过滤高优先级规则失败: threshold={}", priorityThreshold, e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<SpatialRule> resolveRuleConflicts(List<SpatialRule> conflictingRules, MovingObjectType vehicleType, LocalDateTime timestamp) {
        if (conflictingRules == null || conflictingRules.isEmpty()) {
            return new ArrayList<>();
        }

        try {
            // 基本冲突解决：按优先级排序，取第一个
            List<SpatialRule> sorted = sortRulesByPriority(conflictingRules, vehicleType, timestamp);
            return List.of(sorted.get(0));

        } catch (Exception e) {
            logger.error("解决规则冲突失败", e);
            return conflictingRules.subList(0, Math.min(1, conflictingRules.size()));
        }
    }

    @Override
    public boolean hasPriorityConflicts(List<SpatialRule> rules) {
        if (rules == null || rules.size() < 2) {
            return false;
        }

        try {
            Map<Integer, Long> priorityGroups = rules.stream()
                    .collect(Collectors.groupingBy(SpatialRule::getPriority, Collectors.counting()));
            
            return priorityGroups.values().stream().anyMatch(count -> count > 1);

        } catch (Exception e) {
            logger.error("检查优先级冲突失败", e);
            return false;
        }
    }

    @Override
    public int getEffectivePriority(SpatialRule rule, MovingObjectType vehicleType, LocalDateTime timestamp) {
        try {
            int basePriority = rule.getPriority();
            
            // 车辆类型调整
            if (vehicleType != null) {
                int vehiclePermissionLevel = vehicleTypePermissionService.getVehicleTypePermissionLevel(vehicleType);
                // 高权限车辆的规则优先级提升
                if (vehiclePermissionLevel <= 2) {
                    basePriority -= 1;
                }
            }
            
            // 时间因素调整
            if (timestamp != null) {
                LocalTime time = timestamp.toLocalTime();
                // 夜间时间（22:00-06:00）提升安全相关规则优先级
                if (isNightTime(time) && isSafetyRelatedRule(rule)) {
                    basePriority -= 1;
                }
                
                // 高峰时间（07:00-09:00, 17:00-19:00）提升优先级控制规则
                if (isPeakTime(time) && rule.getCategory() == RuleCategory.PRIORITY_CONTROL) {
                    basePriority -= 1;
                }
            }
            
            return Math.max(1, basePriority); // 确保优先级不小于1

        } catch (Exception e) {
            logger.warn("计算有效优先级失败: ruleId={}", rule.getRuleId(), e);
            return rule.getPriority();
        }
    }

    @Override
    public int getCategoryDefaultPriority(RuleCategory category) {
        return CATEGORY_DEFAULT_PRIORITIES.getOrDefault(category, 999);
    }

    @Override
    public double calculateUrgencyScore(SpatialRule rule, MovingObjectType vehicleType, LocalDateTime timestamp) {
        try {
            double baseScore = 1.0 / rule.getPriority(); // 优先级越小分数越高
            
            // 应用类别紧急系数
            double categoryFactor = URGENCY_FACTORS.getOrDefault(rule.getCategory(), 1.0);
            baseScore *= categoryFactor;
            
            // 车辆类型影响
            if (vehicleType != null) {
                if (vehicleTypePermissionService.hasSpecialPermission(vehicleType)) {
                    baseScore *= 1.5; // 特殊权限车辆紧急系数
                }
                
                int vehiclePermissionLevel = vehicleTypePermissionService.getVehicleTypePermissionLevel(vehicleType);
                baseScore *= (4.0 - vehiclePermissionLevel) / 3.0; // 权限级别影响
            }
            
            // 时间因素影响
            if (timestamp != null) {
                LocalTime time = timestamp.toLocalTime();
                if (isNightTime(time) && isSafetyRelatedRule(rule)) {
                    baseScore *= 1.3; // 夜间安全规则更紧急
                }
            }
            
            return baseScore;

        } catch (Exception e) {
            logger.warn("计算紧急程度失败: ruleId={}", rule.getRuleId(), e);
            return 1.0 / rule.getPriority();
        }
    }

    @Override
    public List<SpatialRule> sortRulesByUrgency(List<SpatialRule> rules, MovingObjectType vehicleType, LocalDateTime timestamp) {
        if (rules == null || rules.isEmpty()) {
            return new ArrayList<>();
        }

        try {
            return rules.stream()
                    .sorted(Comparator
                            .comparing((SpatialRule rule) -> calculateUrgencyScore(rule, vehicleType, timestamp))
                            .reversed() // 紧急程度高的在前
                            .thenComparing(SpatialRule::getRuleId)) // 确保稳定排序
                    .collect(Collectors.toList());

        } catch (Exception e) {
            logger.error("按紧急程度排序失败", e);
            return sortRulesByPriority(rules);
        }
    }

    @Override
    public PriorityStatistics getPriorityStatistics(List<SpatialRule> rules) {
        if (rules == null || rules.isEmpty()) {
            return new PriorityStatistics(0, 0, 0, 0.0, new HashMap<>(), new HashMap<>(), 0);
        }

        try {
            int totalRules = rules.size();
            
            IntSummaryStatistics stats = rules.stream()
                    .mapToInt(SpatialRule::getPriority)
                    .summaryStatistics();
            
            Map<Integer, Long> priorityDistribution = rules.stream()
                    .collect(Collectors.groupingBy(SpatialRule::getPriority, Collectors.counting()));
            
            Map<RuleCategory, Integer> categoryAveragePriorities = rules.stream()
                    .collect(Collectors.groupingBy(
                            SpatialRule::getCategory,
                            Collectors.collectingAndThen(
                                    Collectors.averagingInt(SpatialRule::getPriority),
                                    Double::intValue
                            )
                    ));
            
            int conflictingRulesCount = (int) priorityDistribution.values().stream()
                    .filter(count -> count > 1)
                    .mapToLong(Long::longValue)
                    .sum();
            
            return new PriorityStatistics(
                    totalRules,
                    stats.getMin(),
                    stats.getMax(),
                    stats.getAverage(),
                    priorityDistribution,
                    categoryAveragePriorities,
                    conflictingRulesCount
            );

        } catch (Exception e) {
            logger.error("获取优先级统计失败", e);
            return new PriorityStatistics(0, 0, 0, 0.0, new HashMap<>(), new HashMap<>(), 0);
        }
    }

    @Override
    public PriorityValidationResult validatePriorityConfiguration(List<SpatialRule> rules) {
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();
        List<String> recommendations = new ArrayList<>();
        List<RuleConflict> conflicts = new ArrayList<>();

        try {
            if (rules == null || rules.isEmpty()) {
                warnings.add("规则列表为空，无法进行优先级验证");
                return new PriorityValidationResult(true, errors, warnings, recommendations, conflicts);
            }

            // 检查优先级范围
            IntSummaryStatistics stats = rules.stream()
                    .mapToInt(SpatialRule::getPriority)
                    .summaryStatistics();
            
            if (stats.getMin() < 1) {
                errors.add("发现无效的优先级值（小于1）: " + stats.getMin());
            }
            
            if (stats.getMax() > 1000) {
                warnings.add("优先级值过大（大于1000）: " + stats.getMax());
            }
            
            // 检查优先级分布
            Map<Integer, List<SpatialRule>> priorityGroups = rules.stream()
                    .collect(Collectors.groupingBy(SpatialRule::getPriority));
            
            for (Map.Entry<Integer, List<SpatialRule>> entry : priorityGroups.entrySet()) {
                if (entry.getValue().size() > 1) {
                    conflicts.add(new RuleConflict(
                            entry.getValue(),
                            "PRIORITY_CONFLICT",
                            "多个规则具有相同优先级: " + entry.getKey(),
                            5
                    ));
                }
            }
            
            // 检查类别优先级合理性
            Map<RuleCategory, List<SpatialRule>> categoryGroups = rules.stream()
                    .collect(Collectors.groupingBy(SpatialRule::getCategory));
            
            for (Map.Entry<RuleCategory, List<SpatialRule>> entry : categoryGroups.entrySet()) {
                RuleCategory category = entry.getKey();
                int avgPriority = (int) entry.getValue().stream()
                        .mapToInt(SpatialRule::getPriority)
                        .average()
                        .orElse(0);
                
                int expectedPriority = getCategoryDefaultPriority(category);
                if (Math.abs(avgPriority - expectedPriority) > 5) {
                    recommendations.add(String.format(
                            "类别 %s 的平均优先级(%d)与建议值(%d)相差较大",
                            category, avgPriority, expectedPriority
                    ));
                }
            }
            
            // 检查安全关键规则
            long safetyRulesCount = rules.stream()
                    .filter(this::isSafetyRelatedRule)
                    .filter(rule -> rule.getPriority() > 10)
                    .count();
            
            if (safetyRulesCount > 0) {
                warnings.add(String.format("发现%d个安全关键规则的优先级较低（>10）", safetyRulesCount));
            }

        } catch (Exception e) {
            errors.add("验证优先级配置时发生异常: " + e.getMessage());
        }

        return new PriorityValidationResult(errors.isEmpty(), errors, warnings, recommendations, conflicts);
    }

    // ============================================
    // 私有辅助方法
    // ============================================

    private boolean isNightTime(LocalTime time) {
        return time.isBefore(LocalTime.of(6, 0)) || time.isAfter(LocalTime.of(22, 0));
    }

    private boolean isPeakTime(LocalTime time) {
        return (time.isAfter(LocalTime.of(7, 0)) && time.isBefore(LocalTime.of(9, 0))) ||
               (time.isAfter(LocalTime.of(17, 0)) && time.isBefore(LocalTime.of(19, 0)));
    }

    private boolean isSafetyRelatedRule(SpatialRule rule) {
        return rule.getCategory() == RuleCategory.SAFETY_ZONE ||
               rule.getCategory() == RuleCategory.ACCESS_CONTROL ||
               rule.getCategory() == RuleCategory.SPEED_LIMIT;
    }
} 