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.common.model.spatial.AirportArea;
import com.qaup.collision.common.service.AirportAreaService;
import com.qaup.collision.rule.event.RuleEventPublisher;
import com.qaup.collision.rule.model.entity.SpatialRule;
import com.qaup.collision.rule.model.enums.RuleCategory;
import com.qaup.collision.rule.model.enums.RuleStatus;
import com.qaup.collision.rule.model.enums.SpatialObjectType;
import com.qaup.collision.rule.repository.SpatialRuleRepository;
import com.qaup.collision.rule.service.SpatialRuleService;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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
@Transactional
public class SpatialRuleServiceImpl implements SpatialRuleService {

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

    @Autowired
    private SpatialRuleRepository spatialRuleRepository;
    
    @Autowired
    private RuleEventPublisher ruleEventPublisher;

    @Autowired
    private ObjectMapper objectMapper;
    
    @Autowired
    private AirportAreaService airportAreaService;

    // ========== 规则基础管理 ==========

    @Override
    public SpatialRule createRule(SpatialRule rule) {
        logger.info("创建新的空间规则: {}", rule.getName());
        
        // 验证规则有效性
        RuleValidationResult validation = validateRule(rule);
        if (!validation.isValid()) {
            throw new IllegalArgumentException("规则验证失败: " + String.join(", ", validation.getErrors()));
        }
        
        // 设置创建时间和默认状态
        rule.setCreatedAt(LocalDateTime.now());
        rule.setUpdatedAt(LocalDateTime.now());
        if (rule.getStatus() == null) {
            rule.setStatus(RuleStatus.ACTIVE);
        }
        
        // 生成规则ID（如果未提供）
        if (rule.getRuleId() == null || rule.getRuleId().isEmpty()) {
            rule.setRuleId(generateRuleId(rule));
        }
        
        SpatialRule savedRule = spatialRuleRepository.save(rule);
        logger.info("成功创建规则: {}", savedRule.getRuleId());
        
        // 清除相关缓存
        clearRuleCache();
        
        return savedRule;
    }

    @Override
    public List<SpatialRule> createRules(List<SpatialRule> rules) {
        logger.info("批量创建空间规则，数量: {}", rules.size());
        
        List<SpatialRule> savedRules = new ArrayList<>();
        for (SpatialRule rule : rules) {
            try {
                savedRules.add(createRule(rule));
            } catch (Exception e) {
                logger.error("创建规则失败: {}, 错误: {}", rule.getName(), e.getMessage());
                throw new IllegalArgumentException("批量创建规则失败，在规则: " + rule.getName(), e);
            }
        }
        
        return savedRules;
    }

    @Override
    public SpatialRule updateRule(String ruleId, SpatialRule rule) {
        logger.info("更新空间规则: {}", ruleId);
        
        Optional<SpatialRule> existingRuleOpt = spatialRuleRepository.findById(ruleId);
        if (!existingRuleOpt.isPresent()) {
            throw new IllegalArgumentException("规则不存在: " + ruleId);
        }
        
        // 验证更新的规则
        RuleValidationResult validation = validateRule(rule);
        if (!validation.isValid()) {
            throw new IllegalArgumentException("规则验证失败: " + String.join(", ", validation.getErrors()));
        }
        
        SpatialRule existingRule = existingRuleOpt.get();
        
        // 更新字段
        existingRule.setName(rule.getName());
        existingRule.setDescription(rule.getDescription());
        existingRule.setCategory(rule.getCategory());
        existingRule.setSpatialObjectType(rule.getSpatialObjectType());
        existingRule.setSpatialObjectId(rule.getSpatialObjectId());
        existingRule.setCustomGeometry(rule.getCustomGeometry());
        existingRule.setAllowedVehicleTypes(rule.getAllowedVehicleTypes());
        existingRule.setParameters(rule.getParameters());
        existingRule.setPriority(rule.getPriority());
        existingRule.setEffectiveStartTime(rule.getEffectiveStartTime());
        existingRule.setEffectiveEndTime(rule.getEffectiveEndTime());
        existingRule.setDailyStartTime(rule.getDailyStartTime());
        existingRule.setDailyEndTime(rule.getDailyEndTime());
        existingRule.setWeekdayPattern(rule.getWeekdayPattern());
        existingRule.setStatus(rule.getStatus());
        existingRule.setUpdatedAt(LocalDateTime.now());
        
        SpatialRule savedRule = spatialRuleRepository.save(existingRule);
        logger.info("成功更新规则: {}", ruleId);
        
        // 清除相关缓存
        clearRuleCache();
        
        return savedRule;
    }

    @Override
    public boolean deleteRule(String ruleId) {
        logger.info("删除空间规则: {}", ruleId);
        
        if (!spatialRuleRepository.existsById(ruleId)) {
            logger.warn("试图删除不存在的规则: {}", ruleId);
            return false;
        }
        
        spatialRuleRepository.deleteById(ruleId);
        logger.info("成功删除规则: {}", ruleId);
        
        // 清除相关缓存
        clearRuleCache();
        
        return true;
    }

    @Override
    public int deleteRules(List<String> ruleIds) {
        logger.info("批量删除空间规则，数量: {}", ruleIds.size());
        
        int deletedCount = 0;
        for (String ruleId : ruleIds) {
            if (deleteRule(ruleId)) {
                deletedCount++;
            }
        }
        
        logger.info("批量删除完成，成功删除: {}", deletedCount);
        return deletedCount;
    }

    @Override
    @Cacheable(value = "spatialRules", key = "#ruleId")
    public Optional<SpatialRule> findRuleById(String ruleId) {
        return spatialRuleRepository.findById(ruleId);
    }

    @Override
    @Cacheable(value = "allSpatialRules")
    public List<SpatialRule> findAllRules() {
        return spatialRuleRepository.findAll();
    }

    // ========== 规则状态管理 ==========

    @Override
    @CacheEvict(value = "spatialRules", key = "#ruleId")
    public boolean enableRule(String ruleId) {
        return updateRuleStatus(ruleId, RuleStatus.ACTIVE);
    }

    @Override
    @CacheEvict(value = "spatialRules", key = "#ruleId")
    public boolean disableRule(String ruleId) {
        return updateRuleStatus(ruleId, RuleStatus.SUSPENDED);
    }

    @Override
    public int enableRules(List<String> ruleIds) {
        return updateRulesStatus(ruleIds, RuleStatus.ACTIVE);
    }

    @Override
    public int disableRules(List<String> ruleIds) {
        return updateRulesStatus(ruleIds, RuleStatus.SUSPENDED);
    }

    @Override
    @CacheEvict(value = "spatialRules", key = "#ruleId")
    public boolean setRuleValidPeriod(String ruleId, LocalDateTime validFrom, LocalDateTime validTo) {
        logger.info("设置规则有效期: {}, 从 {} 到 {}", ruleId, validFrom, validTo);
        
        Optional<SpatialRule> ruleOpt = spatialRuleRepository.findById(ruleId);
        if (!ruleOpt.isPresent()) {
            logger.warn("规则不存在: {}", ruleId);
            return false;
        }
        
        SpatialRule rule = ruleOpt.get();
        rule.setEffectiveStartTime(validFrom);
        rule.setEffectiveEndTime(validTo);
        rule.setUpdatedAt(LocalDateTime.now());
        
        spatialRuleRepository.save(rule);
        logger.info("成功设置规则有效期: {}", ruleId);
        
        return true;
    }

    // ========== 规则查询和筛选 ==========

    @Override
    @Cacheable(value = "rulesByCategory", key = "#category")
    public List<SpatialRule> findRulesByCategory(RuleCategory category) {
        return spatialRuleRepository.findByCategory(category);
    }

    @Override
    @Cacheable(value = "rulesByStatus", key = "#status")
    public List<SpatialRule> findRulesByStatus(RuleStatus status) {
        return spatialRuleRepository.findByStatus(status);
    }

    @Override
    @Cacheable(value = "rulesBySpatialObjectType", key = "#objectType")
    public List<SpatialRule> findRulesBySpatialObjectType(SpatialObjectType objectType) {
        return spatialRuleRepository.findBySpatialObjectType(objectType);
    }

    @Override
    @Cacheable(value = "rulesByObjectId", key = "#objectId")
    public List<SpatialRule> findRulesByObjectId(String objectId) {
        // 使用通用的spatialObjectId查询
        return spatialRuleRepository.findBySpatialObjectId(objectId);
    }

    @Override
    public List<SpatialRule> findRulesByPriorityRange(Integer minPriority, Integer maxPriority) {
        return spatialRuleRepository.findByPriorityRangeAndStatus(minPriority, maxPriority, RuleStatus.ACTIVE);
    }

    @Override
    @Cacheable(value = "activeRules")
    public List<SpatialRule> findActiveRules() {
        LocalDateTime now = LocalDateTime.now();
        return spatialRuleRepository.findCurrentlyEffectiveRules(now);
    }

    @Override
    public List<SpatialRule> findExpiringRules(LocalDateTime beforeTime) {
        return spatialRuleRepository.findRulesExpiringBefore(beforeTime);
    }

    // ========== 空间查询功能 ==========

    @Override
    @Cacheable(value = "applicableRules", key = "#location.x + '_' + #location.y + '_' + #vehicleType")
    public List<SpatialRule> findApplicableRules(Point location, MovingObjectType vehicleType) {
        return findApplicableRules(location, vehicleType, LocalDateTime.now());
    }

    @Override
    public List<SpatialRule> findApplicableRules(Point location, MovingObjectType vehicleType, LocalDateTime timestamp) {
        logger.debug("查找适用规则 - 位置: {}, 车辆类型: {}, 时间: {}", location, vehicleType, timestamp);
        
        // 查找空间上包含该位置的规则
        List<SpatialRule> spatialRules = spatialRuleRepository.findCustomGeometryRulesContainingPoint(location);
        
        // 过滤出适用的规则
        return spatialRules.stream()
                .filter(rule -> isRuleApplicable(rule, vehicleType, timestamp))
                .sorted(Comparator.comparing(SpatialRule::getPriority))
                .collect(Collectors.toList());
    }

    @Override
    public List<SpatialRule> findRulesIntersecting(Geometry geometry) {
        // 由于Repository中没有直接的几何相交查询，这里返回所有自定义几何规则
        return spatialRuleRepository.findBySpatialObjectType(SpatialObjectType.CUSTOM_GEOMETRY);
    }

    @Override
    public List<SpatialRule> findRulesContaining(Point location) {
        return spatialRuleRepository.findCustomGeometryRulesContainingPoint(location);
    }

    @Override
    public List<SpatialRule> findRulesWithinRadius(Point center, double radiusMeters) {
        // 由于Repository中没有直接的半径查询，这里返回所有自定义几何规则
        return spatialRuleRepository.findBySpatialObjectType(SpatialObjectType.CUSTOM_GEOMETRY);
    }

    @Override
    @Cacheable(value = "spatialRules", key = "'byLocation_' + #location.x + '_' + #location.y + '_' + #timestamp")
    public List<SpatialRule> findRulesByLocation(Point location, LocalDateTime timestamp) {
        logger.debug("查询位置相关规则: 位置({}, {}), 时间{}", location.getX(), location.getY(), timestamp);
        
        // 查找包含该位置的规则
        List<SpatialRule> containingRules = findRulesContaining(location);
        
        // 过滤时间有效的规则
        return containingRules.stream()
            .filter(rule -> isRuleTimeValid(rule, timestamp))
            .filter(rule -> rule.getStatus() == RuleStatus.ACTIVE)
            .sorted((r1, r2) -> Integer.compare(r2.getPriority(), r1.getPriority()))
            .collect(Collectors.toList());
    }

    @Override
    public boolean isLocationInArea(Point location, String areaId) {
        try {
            logger.debug("检查位置是否在区域内: 位置({}, {}), 区域ID{}", location.getX(), location.getY(), areaId);
            
            // 使用AirportAreaService查询指定区域ID
            Optional<AirportArea> areaOpt = airportAreaService.getAreaByAreaId(areaId);
            if (!areaOpt.isPresent()) {
                logger.warn("区域不存在: areaId={}", areaId);
                return false;
            }
            
            AirportArea area = areaOpt.get();
            if (area.getEnabled() == null || !area.getEnabled()) {
                logger.debug("区域已禁用: areaId={}", areaId);
                return false;
            }
            
            // 检查点是否在区域边界内
            if (area.getBoundary() == null) {
                logger.warn("区域边界为空: areaId={}", areaId);
                return false;
            }
            
            boolean contains = area.getBoundary().contains(location);
            logger.debug("位置在区域内检查结果: areaId={}, contains={}", areaId, contains);
            
            return contains;
            
        } catch (Exception e) {
            logger.error("检查位置是否在区域内时发生错误: areaId={}, location=({}, {}), error={}", 
                        areaId, location.getX(), location.getY(), e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean isLocationOnRoad(Point location, String roadId) {
        try {
            logger.debug("检查位置是否在道路上: 位置({}, {}), 道路ID{}", location.getX(), location.getY(), roadId);
            
            // 这里应该查询roads表或相关的道路表
            // 暂时返回简单的空间查询结果
            logger.warn("isLocationOnRoad方法需要实现具体的空间查询逻辑");
            return false;
            
        } catch (Exception e) {
            logger.error("检查位置是否在道路上时发生错误: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean isLocationAtIntersection(Point location, String intersectionId) {
        try {
            logger.debug("检查位置是否在路口: 位置({}, {}), 路口ID{}", location.getX(), location.getY(), intersectionId);
            
            // 这里应该查询intersections表或相关的路口表
            // 暂时返回简单的空间查询结果
            logger.warn("isLocationAtIntersection方法需要实现具体的空间查询逻辑");
            return false;
            
        } catch (Exception e) {
            logger.error("检查位置是否在路口时发生错误: {}", e.getMessage(), e);
            return false;
        }
    }

    @Override
    public boolean isLocationInCustomGeometry(Point location, Geometry geometry) {
        try {
            if (geometry == null) {
                return false;
            }
            
            logger.debug("检查位置是否在自定义几何形状内: 位置({}, {})", location.getX(), location.getY());
            
            // 使用JTS进行几何计算
            return geometry.contains(location);
            
        } catch (Exception e) {
            logger.error("检查位置是否在自定义几何形状内时发生错误: {}", e.getMessage(), e);
            return false;
        }
    }

    // ========== 规则执行和检测 ==========

    @Override
    public boolean checkRuleViolation(String ruleId, String vehicleId, MovingObjectType vehicleType, 
                                      Point location, Map<String, Object> vehicleState) {
        Optional<SpatialRule> ruleOpt = findRuleById(ruleId);
        if (!ruleOpt.isPresent()) {
            logger.warn("规则不存在: {}", ruleId);
            return false;
        }
        
        RuleExecutionContext context = executeRule(ruleOpt.get(), vehicleId, vehicleType, 
                                                   location, vehicleState, LocalDateTime.now());
        return context.isViolated();
    }

    @Override
    public List<SpatialRule> checkAllRuleViolations(String vehicleId, MovingObjectType vehicleType, 
                                                     Point location, Map<String, Object> vehicleState) {
        return checkAllRuleViolations(vehicleId, vehicleType, location, vehicleState, LocalDateTime.now());
    }

    @Override
    public List<SpatialRule> checkAllRuleViolations(String vehicleId, MovingObjectType vehicleType, 
                                                     Point location, Map<String, Object> vehicleState, 
                                                     LocalDateTime timestamp) {
        logger.debug("检查所有规则违规 - 车辆: {}, 类型: {}, 位置: {}", vehicleId, vehicleType, location);
        
        // 获取适用的规则
        List<SpatialRule> applicableRules = findApplicableRules(location, vehicleType, timestamp);
        
        // 检查每个规则是否违规
        List<SpatialRule> violatedRules = new ArrayList<>();
        for (SpatialRule rule : applicableRules) {
            RuleExecutionContext context = executeRule(rule, vehicleId, vehicleType, 
                                                       location, vehicleState, timestamp);
            if (context.isViolated()) {
                violatedRules.add(rule);
                logger.warn("规则违规 - 车辆: {}, 规则: {}, 描述: {}", 
                           vehicleId, rule.getRuleId(), context.getDescription());
            }
        }
        
        return violatedRules;
    }

    @Override
    public RuleExecutionContext executeRule(SpatialRule rule, String vehicleId, MovingObjectType vehicleType, 
                                            Point location, Map<String, Object> vehicleState, LocalDateTime timestamp) {
        logger.debug("执行规则检查 - 规则: {}, 车辆: {}", rule.getRuleId(), vehicleId);
        
        // 检查规则是否适用
        boolean applicable = isRuleApplicable(rule, vehicleType, timestamp);
        if (!applicable) {
            return new RuleExecutionContext(rule, vehicleId, vehicleType, location, vehicleState, timestamp,
                                            false, false, "规则不适用", Collections.emptyMap());
        }
        
        // 执行具体的规则检查逻辑
        boolean violated = false;
        String description = "";
        Map<String, Object> executionDetails = new HashMap<>();
        
        try {
            switch (rule.getCategory()) {
                case ACCESS_CONTROL:
                    violated = checkAccessControlViolation(rule, vehicleType, location);
                    description = violated ? "车辆类型不允许进入该区域" : "准入检查通过";
                    break;
                    
                case SPEED_LIMIT:
                    violated = checkSpeedLimitViolation(rule, vehicleState);
                    description = violated ? "超速违规" : "速度检查通过";
                    break;
                    
                case VEHICLE_RESTRICTION:
                    violated = checkVehicleRestrictionViolation(rule, vehicleType, vehicleState);
                    description = violated ? "车辆限制违规" : "车辆限制检查通过";
                    break;
                    
                default:
                    description = "未实现的规则类型: " + rule.getCategory();
                    logger.warn(description);
            }
            
            executionDetails.put("ruleCategory", rule.getCategory());
            executionDetails.put("checkTime", timestamp);
            executionDetails.put("vehicleState", vehicleState);
            
        } catch (Exception e) {
            logger.error("规则执行异常 - 规则: {}, 车辆: {}, 错误: {}", 
                        rule.getRuleId(), vehicleId, e.getMessage());
            description = "规则执行异常: " + e.getMessage();
            executionDetails.put("error", e.getMessage());
        }
        
        return new RuleExecutionContext(rule, vehicleId, vehicleType, location, vehicleState, timestamp,
                                        applicable, violated, description, executionDetails);
    }

    // ========== 规则配置验证 ==========

    @Override
    public RuleValidationResult validateRule(SpatialRule rule) {
        List<String> errors = new ArrayList<>();
        List<String> warnings = new ArrayList<>();
        
        // 基础字段验证
        if (rule.getName() == null || rule.getName().trim().isEmpty()) {
            errors.add("规则名称不能为空");
        }
        
        if (rule.getCategory() == null) {
            errors.add("规则分类不能为空");
        }
        
        if (rule.getSpatialObjectType() == null) {
            errors.add("空间对象类型不能为空");
        }
        
        // 几何形状验证
        if (rule.getCustomGeometry() != null && !isGeometryValid(rule.getCustomGeometry())) {
            errors.add("几何形状无效");
        }
        
        // 时间验证
        if (rule.getEffectiveStartTime() != null && rule.getEffectiveEndTime() != null && 
            rule.getEffectiveStartTime().isAfter(rule.getEffectiveEndTime())) {
            errors.add("有效开始时间不能晚于结束时间");
        }
        
        // 优先级验证
        if (rule.getPriority() != null && (rule.getPriority() < 0 || rule.getPriority() > 100)) {
            warnings.add("优先级建议设置在0-100之间");
        }
        
        // 规则参数验证
        if (rule.getParameters() != null && !rule.getParameters().trim().isEmpty()) {
            try {
                JsonNode parameters = parseJsonString(rule.getParameters());
                if (parameters.isNull()) {
                    warnings.add("规则参数为空");
                }
            } catch (Exception e) {
                errors.add("规则参数处理异常: " + e.getMessage());
            }
        }
        
        return new RuleValidationResult(errors.isEmpty(), errors, warnings);
    }

    @Override
    public List<RuleValidationResult> validateRules(List<SpatialRule> rules) {
        return rules.stream()
                .map(this::validateRule)
                .collect(Collectors.toList());
    }

    @Override
    public List<SpatialRule> findConflictingRules(SpatialRule rule) {
        // 查找在相同空间范围内的同类型规则
        List<SpatialRule> potentialConflicts = new ArrayList<>();
        
        if (rule.getCustomGeometry() != null) {
            potentialConflicts = spatialRuleRepository.findBySpatialObjectType(SpatialObjectType.CUSTOM_GEOMETRY);
        }
        
        // 过滤出实际冲突的规则
        return potentialConflicts.stream()
                .filter(existingRule -> !existingRule.getRuleId().equals(rule.getRuleId()))
                .filter(existingRule -> existingRule.getCategory().equals(rule.getCategory()))
                .filter(existingRule -> hasTimeOverlap(rule, existingRule))
                .collect(Collectors.toList());
    }

    @Override
    public boolean isGeometryValid(Geometry geometry) {
        try {
            return geometry != null && geometry.isValid();
        } catch (Exception e) {
            logger.debug("几何形状验证异常: {}", e.getMessage());
            return false;
        }
    }

    // ========== 统计和分析 ==========

    @Override
    @Cacheable(value = "ruleCountByCategory")
    public Map<RuleCategory, Long> getRuleCountByCategory() {
        List<SpatialRule> allRules = findAllRules();
        return allRules.stream()
                .collect(Collectors.groupingBy(SpatialRule::getCategory, Collectors.counting()));
    }

    @Override
    @Cacheable(value = "ruleCountByStatus")
    public Map<RuleStatus, Long> getRuleCountByStatus() {
        List<SpatialRule> allRules = findAllRules();
        return allRules.stream()
                .collect(Collectors.groupingBy(SpatialRule::getStatus, Collectors.counting()));
    }

    @Override
    public RuleExecutionStatistics getRuleExecutionStatistics(LocalDateTime startTime, LocalDateTime endTime) {
        // TODO: 需要实现规则执行历史统计
        // 这里先返回一个基础的统计对象
        return new RuleExecutionStatistics(0L, 0L, 0.0, 
                                           Collections.emptyMap(), Collections.emptyMap());
    }

    @Override
    public List<SpatialRule> getMostActiveRules(int limit, LocalDateTime startTime, LocalDateTime endTime) {
        // TODO: 需要实现基于执行频率的规则排序
        // 这里先返回按创建时间排序的规则
        return findAllRules().stream()
                .filter(rule -> rule.getCreatedAt().isAfter(startTime) && rule.getCreatedAt().isBefore(endTime))
                .sorted(Comparator.comparing(SpatialRule::getCreatedAt).reversed())
                .limit(limit)
                .collect(Collectors.toList());
    }

    // ========== 规则导入导出 ==========

    @Override
    public int importRulesFromConfig(String configData) {
        // TODO: 实现规则配置导入功能
        logger.info("规则导入功能待实现");
        return 0;
    }

    @Override
    public String exportRulesToConfig(List<String> ruleIds) {
        // TODO: 实现规则配置导出功能
        logger.info("规则导出功能待实现");
        return "";
    }

    @Override
    public SpatialRule cloneRule(String sourceRuleId, String targetRuleId) {
        Optional<SpatialRule> sourceRuleOpt = findRuleById(sourceRuleId);
        if (!sourceRuleOpt.isPresent()) {
            throw new IllegalArgumentException("源规则不存在: " + sourceRuleId);
        }
        
        SpatialRule sourceRule = sourceRuleOpt.get();
        SpatialRule clonedRule = new SpatialRule();
        
        // 复制所有字段（除了ID和时间戳）
        clonedRule.setRuleId(targetRuleId);
        clonedRule.setName(sourceRule.getName() + " (复制)");
        clonedRule.setDescription(sourceRule.getDescription());
        clonedRule.setCategory(sourceRule.getCategory());
        clonedRule.setSpatialObjectType(sourceRule.getSpatialObjectType());
        clonedRule.setSpatialObjectId(sourceRule.getSpatialObjectId());
        clonedRule.setCustomGeometry(sourceRule.getCustomGeometry());
        clonedRule.setAllowedVehicleTypes(sourceRule.getAllowedVehicleTypes());
        clonedRule.setParameters(sourceRule.getParameters());
        clonedRule.setPriority(sourceRule.getPriority());
        clonedRule.setEffectiveStartTime(sourceRule.getEffectiveStartTime());
        clonedRule.setEffectiveEndTime(sourceRule.getEffectiveEndTime());
        clonedRule.setDailyStartTime(sourceRule.getDailyStartTime());
        clonedRule.setDailyEndTime(sourceRule.getDailyEndTime());
        clonedRule.setWeekdayPattern(sourceRule.getWeekdayPattern());
        clonedRule.setStatus(RuleStatus.SUSPENDED); // 复制的规则默认暂停
        
        return createRule(clonedRule);
    }

    // ========== 缓存管理 ==========

    @Override
    @CacheEvict(value = {"spatialRules", "allSpatialRules", "rulesByCategory", 
                         "rulesByStatus", "rulesBySpatialObjectType", "rulesByObjectId", 
                         "activeRules", "applicableRules", "ruleCountByCategory", "ruleCountByStatus"}, 
                allEntries = true)
    public void refreshRuleCache() {
        logger.info("刷新规则缓存");
    }

    @Override
    @CacheEvict(value = {"spatialRules", "allSpatialRules", "rulesByCategory", 
                         "rulesByStatus", "rulesBySpatialObjectType", "rulesByObjectId", 
                         "activeRules", "applicableRules", "ruleCountByCategory", "ruleCountByStatus"}, 
                allEntries = true)
    public void clearRuleCache() {
        logger.debug("清空规则缓存");
    }

    @Override
    public void warmupRuleCache(Point location, double radiusMeters) {
        logger.info("预热规则缓存 - 位置: {}, 半径: {}米", location, radiusMeters);
        
        // 预加载该区域内的规则
        findRulesWithinRadius(location, radiusMeters);
        
        // 预加载常用的规则查询
        findActiveRules();
        getRuleCountByCategory();
        getRuleCountByStatus();
    }

    @Override
    public List<SpatialRule> findActiveRulesForArea(String areaCode, RuleCategory category) {
        logger.debug("查找区域的活跃规则 - 区域: {}, 分类: {}", areaCode, category);
        
        try {
            // 查找与指定区域和分类匹配的规则
            List<SpatialRule> allRules = spatialRuleRepository.findBySpatialObjectIdAndCategory(areaCode, category);
            
            // 过滤出当前有效的规则
            List<SpatialRule> activeRules = allRules.stream()
                    .filter(rule -> rule.getStatus() == RuleStatus.ACTIVE)
                    .filter(SpatialRule::isCurrentlyEffective)
                    .sorted(Comparator.comparing(SpatialRule::getPriority))
                    .collect(Collectors.toList());
            
            logger.debug("找到 {} 个活跃规则", activeRules.size());
            return activeRules;
            
        } catch (Exception e) {
            logger.error("查找区域活跃规则失败 - 区域: {}, 分类: {}, 错误: {}", areaCode, category, e.getMessage());
            return Collections.emptyList();
        }
    }

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

    /**
     * 生成规则ID
     */
    private String generateRuleId(SpatialRule rule) {
        String prefix = rule.getCategory().name().toLowerCase();
        String timestamp = String.valueOf(System.currentTimeMillis());
        return prefix + "_" + timestamp;
    }

    /**
     * 更新规则状态
     */
    private boolean updateRuleStatus(String ruleId, RuleStatus status) {
        Optional<SpatialRule> ruleOpt = spatialRuleRepository.findById(ruleId);
        if (!ruleOpt.isPresent()) {
            logger.warn("规则不存在: {}", ruleId);
            return false;
        }
        
        SpatialRule rule = ruleOpt.get();
        RuleStatus previousStatus = rule.getStatus();
        rule.setStatus(status);
        rule.setUpdatedAt(LocalDateTime.now());
        
        spatialRuleRepository.save(rule);
        logger.info("成功更新规则状态: {} -> {}", ruleId, status);
        
        // 发布规则状态变更事件
        String changeReason = status == RuleStatus.ACTIVE ? "规则激活" : "规则停用";
        Map<String, Object> changeContext = Map.of(
            "previousStatus", previousStatus.name(),
            "newStatus", status.name(),
            "updateTime", LocalDateTime.now().toString()
        );
        
        ruleEventPublisher.publishRuleStateChange(rule, previousStatus, status, 
            changeReason, "SystemService", this, changeContext);
        
        return true;
    }

    /**
     * 批量更新规则状态
     */
    private int updateRulesStatus(List<String> ruleIds, RuleStatus status) {
        int updatedCount = 0;
        for (String ruleId : ruleIds) {
            if (updateRuleStatus(ruleId, status)) {
                updatedCount++;
            }
        }
        return updatedCount;
    }

    /**
     * 检查规则是否适用于指定车辆和时间
     */
    private boolean isRuleApplicable(SpatialRule rule, MovingObjectType vehicleType, LocalDateTime timestamp) {
        // 检查规则状态
        if (rule.getStatus() != RuleStatus.ACTIVE) {
            return false;
        }
        
        // 检查有效期
        if (rule.getEffectiveStartTime() != null && timestamp.isBefore(rule.getEffectiveStartTime())) {
            return false;
        }
        if (rule.getEffectiveEndTime() != null && timestamp.isAfter(rule.getEffectiveEndTime())) {
            return false;
        }
        
        // 对于准入控制规则，所有车辆类型都应该适用（以便检测违规）
        // 不在这里过滤车辆类型，由具体的规则执行逻辑来判断是否违规
        
        // TODO: 检查时间模式（如工作日、特定时间段等）
        
        return true;
    }

    /**
     * 检查准入控制违规
     */
    private boolean checkAccessControlViolation(SpatialRule rule, MovingObjectType vehicleType, Point location) {
        // 对于准入控制，如果车辆类型不在允许列表中，则违规
        if (rule.getAllowedVehicleTypes() != null && !rule.getAllowedVehicleTypes().isEmpty()) {
            return !rule.getAllowedVehicleTypes().contains(vehicleType);
        }
        return false;
    }

    /**
     * 检查限速违规
     */
    private boolean checkSpeedLimitViolation(SpatialRule rule, Map<String, Object> vehicleState) {
        try {
            // 从规则参数中获取限速值
            if (rule.getParameters() != null && !rule.getParameters().trim().isEmpty()) {
                JsonNode parameters = parseJsonString(rule.getParameters());
                JsonNode speedLimitNode = parameters.get("maxSpeed");
                if (speedLimitNode != null && !speedLimitNode.isNull()) {
                    double speedLimit = speedLimitNode.asDouble();
                    
                    // 从车辆状态中获取当前速度
                    Object currentSpeedObj = vehicleState.get("speed");
                    if (currentSpeedObj != null) {
                        double currentSpeed = Double.parseDouble(currentSpeedObj.toString());
                        return currentSpeed > speedLimit;
                    }
                }
            }
        } catch (Exception e) {
            logger.error("检查限速违规时发生异常: {}", e.getMessage());
        }
        return false;
    }

    /**
     * 检查车辆限制违规
     */
    private boolean checkVehicleRestrictionViolation(SpatialRule rule, MovingObjectType vehicleType, 
                                                     Map<String, Object> vehicleState) {
        try {
            if (rule.getParameters() != null && !rule.getParameters().trim().isEmpty()) {
                JsonNode parameters = parseJsonString(rule.getParameters());
                JsonNode maxHeightNode = parameters.get("maxHeight");
                if (maxHeightNode != null && !maxHeightNode.isNull()) {
                    double maxHeight = maxHeightNode.asDouble();
                    Object heightObj = vehicleState.get("height");
                    if (heightObj != null) {
                        double height = Double.parseDouble(heightObj.toString());
                        if (height > maxHeight) {
                            return true;
                        }
                    }
                }
                
                JsonNode maxWeightNode = parameters.get("maxWeight");
                if (maxWeightNode != null && !maxWeightNode.isNull()) {
                    double maxWeight = maxWeightNode.asDouble();
                    Object weightObj = vehicleState.get("weight");
                    if (weightObj != null) {
                        double weight = Double.parseDouble(weightObj.toString());
                        if (weight > maxWeight) {
                            return true;
                        }
                    }
                }
            }
        } catch (Exception e) {
            logger.error("检查车辆限制违规时发生异常: {}", e.getMessage());
        }
        return false;
    }

    /**
     * 检查两个规则的时间是否重叠
     */
    private boolean hasTimeOverlap(SpatialRule rule1, SpatialRule rule2) {
        LocalDateTime start1 = rule1.getEffectiveStartTime();
        LocalDateTime end1 = rule1.getEffectiveEndTime();
        LocalDateTime start2 = rule2.getEffectiveStartTime();
        LocalDateTime end2 = rule2.getEffectiveEndTime();
        
        // 如果任一规则没有时间限制，则认为有重叠
        if (start1 == null || end1 == null || start2 == null || end2 == null) {
            return true;
        }
        
        // 检查时间段是否重叠
        return !(end1.isBefore(start2) || start1.isAfter(end2));
    }

    /**
     * 检查规则在指定时间是否有效
     */
    private boolean isRuleTimeValid(SpatialRule rule, LocalDateTime timestamp) {
        // 检查有效期
        if (rule.getEffectiveStartTime() != null && timestamp.isBefore(rule.getEffectiveStartTime())) {
            return false;
        }
        
        if (rule.getEffectiveEndTime() != null && timestamp.isAfter(rule.getEffectiveEndTime())) {
            return false;
        }
        
        // 优先检查复杂时间模式
        if (rule.getTimePatterns() != null && !rule.getTimePatterns().trim().isEmpty()) {
            JsonNode timePatterns = parseJsonString(rule.getTimePatterns());
            if (timePatterns != null && !timePatterns.isNull()) {
                return matchesTimePatterns(timePatterns, timestamp);
            }
        }
        
        // 检查每日时间范围
        if (rule.getDailyStartTime() != null && rule.getDailyEndTime() != null) {
            return matchesDailyTimeRange(rule.getDailyStartTime(), rule.getDailyEndTime(), timestamp);
        }
        
        // 检查星期模式
        if (rule.getWeekdayPattern() != null) {
            return matchesWeekdayPattern(rule.getWeekdayPattern(), timestamp);
        }
        
        return true;
    }

    /**
     * 检查每日时间范围匹配
     */
    private boolean matchesDailyTimeRange(LocalTime startTime, LocalTime endTime, LocalDateTime timestamp) {
        try {
            LocalTime currentTime = timestamp.toLocalTime();
            
            if (startTime.isBefore(endTime)) {
                // 同一天内的时间范围
                return !currentTime.isBefore(startTime) && !currentTime.isAfter(endTime);
            } else {
                // 跨天的时间范围
                return !currentTime.isBefore(startTime) || !currentTime.isAfter(endTime);
            }
        } catch (Exception e) {
            logger.warn("检查每日时间范围失败: {} - {}", startTime, endTime, e);
            return true; // 默认匹配
        }
    }

    /**
     * 检查星期模式匹配
     */
    private boolean matchesWeekdayPattern(Integer weekdayPattern, LocalDateTime timestamp) {
        try {
            // 获取当前是星期几（1=周一, 2=周二, ..., 7=周日）
            int dayOfWeek = timestamp.getDayOfWeek().getValue();
            
            // 计算对应的位掩码（周一=1, 周二=2, 周三=4, ..., 周日=64）
            int dayMask = 1 << (dayOfWeek - 1);
            
            // 检查当前星期是否在模式中
            return (weekdayPattern & dayMask) != 0;
        } catch (Exception e) {
            logger.warn("检查星期模式失败: {}", weekdayPattern, e);
            return true; // 默认匹配
        }
    }

    /**
     * 检查复杂时间模式匹配
     * 支持JSONB格式的时间表达式：[{"days": ["MONDAY", "TUESDAY"], "time_ranges": ["08:00-18:00"]}]
     */
    private boolean matchesTimePatterns(JsonNode timePatterns, LocalDateTime timestamp) {
        try {
            if (!timePatterns.isArray()) {
                return true; // 默认匹配
            }
            
            // 遍历时间模式数组
            for (JsonNode pattern : timePatterns) {
                if (matchesSingleTimePattern(pattern, timestamp)) {
                    return true; // 任意一个模式匹配即可
                }
            }
            
            return false; // 所有模式都不匹配
            
        } catch (Exception e) {
            logger.warn("解析时间模式失败: {}", timePatterns, e);
            return true; // 默认匹配
        }
    }

    /**
     * 检查单个时间模式匹配
     */
    private boolean matchesSingleTimePattern(JsonNode pattern, LocalDateTime timestamp) {
        try {
            // 检查星期
            JsonNode daysNode = pattern.get("days");
            if (daysNode != null && daysNode.isArray()) {
                boolean dayMatches = false;
                String currentDay = timestamp.getDayOfWeek().name();
                
                for (JsonNode dayNode : daysNode) {
                    if (dayNode.asText().equalsIgnoreCase(currentDay)) {
                        dayMatches = true;
                        break;
                    }
                }
                
                if (!dayMatches) {
                    return false;
                }
            }
            
            // 检查时间范围
            JsonNode timeRangesNode = pattern.get("time_ranges");
            if (timeRangesNode != null && timeRangesNode.isArray()) {
                for (JsonNode timeRangeNode : timeRangesNode) {
                    String timeRange = timeRangeNode.asText();
                    if (parseTimeRange(timeRange, timestamp)) {
                        return true; // 任意一个时间范围匹配即可
                    }
                }
                return false; // 所有时间范围都不匹配
            }
            
            return true; // 没有时间限制，默认匹配
            
        } catch (Exception e) {
            logger.warn("解析单个时间模式失败: {}", pattern, e);
            return true; // 默认匹配
        }
    }

    /**
     * 解析时间范围 "HH:mm-HH:mm"
     */
    private boolean parseTimeRange(String timeRange, LocalDateTime timestamp) {
        try {
            String[] parts = timeRange.split("-");
            if (parts.length == 2) {
                LocalTime startTime = LocalTime.parse(parts[0].trim());
                LocalTime endTime = LocalTime.parse(parts[1].trim());
                return matchesDailyTimeRange(startTime, endTime, timestamp);
            }
        } catch (Exception e) {
            logger.warn("解析时间范围失败: {}", timeRange, e);
        }
        return true;
    }

    /**
     * 检查星期名称匹配 "MON,WED,FRI"
     */
    private boolean matchesWeekdayNames(String weekdays, LocalDateTime timestamp) {
        try {
            String[] dayNames = weekdays.split(",");
            String currentDay = timestamp.getDayOfWeek().name().substring(0, 3); // MON, TUE, etc.
            
            for (String dayName : dayNames) {
                if (dayName.trim().equalsIgnoreCase(currentDay)) {
                    return true;
                }
            }
            return false;
        } catch (Exception e) {
            logger.warn("检查星期名称失败: {}", weekdays, e);
            return true;
        }
    }

    private JsonNode parseJsonString(String jsonString) {
        try {
            if (jsonString == null || jsonString.trim().isEmpty()) {
                return objectMapper.createObjectNode();
            }
            return objectMapper.readTree(jsonString);
        } catch (Exception e) {
            logger.warn("解析JSON字符串失败: {}", jsonString, e);
            return objectMapper.createObjectNode();
        }
    }
} 