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

import com.qaup.collision.common.model.MovingObject.MovingObjectType;
import com.qaup.collision.common.model.spatial.VehicleLocation;
import com.qaup.collision.rule.event.RuleViolationEvent;
import com.qaup.collision.rule.event.RuleViolationEventOccurred; // 导入RuleViolationEventOccurred
import com.qaup.collision.rule.model.entity.SpatialRule;
import com.qaup.collision.rule.model.enums.RuleAlertLevel;
import com.qaup.collision.rule.model.enums.RuleCategory;
import com.qaup.collision.rule.model.enums.ViolationType;
import com.qaup.collision.rule.repository.RuleViolationEventRepository;
import com.qaup.collision.rule.service.LocationRuleQueryService;
import com.qaup.collision.rule.service.RealTimeViolationDetector;
import com.qaup.collision.rule.service.RuleExecutionEngine;
import com.qaup.collision.rule.service.RuleViolationProcessor;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Point;

import org.springframework.stereotype.Service;
import org.springframework.context.event.EventListener; // 导入EventListener

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 实时违规检测服务实现类
 * 集成规则执行引擎和违规事件处理器，提供完整的实时违规检测功能
 * 
 * @author AI Assistant
 * @version 1.0
 * @since 2025-01-17
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class RealTimeViolationDetectorImpl implements RealTimeViolationDetector {

    private final LocationRuleQueryService locationRuleQueryService;
    private final RuleExecutionEngine ruleExecutionEngine;
    private final RuleViolationProcessor ruleViolationProcessor;
    private final RuleViolationEventRepository violationEventRepository;

    // 配置参数
    private final AtomicBoolean realTimeDetectionEnabled = new AtomicBoolean(true);
    private final Map<String, Object> detectionConfig = new HashMap<>();
    
    // 性能指标
    private final AtomicLong totalDetections = new AtomicLong(0);
    private final AtomicLong totalViolations = new AtomicLong(0);
    private final AtomicLong totalProcessingTime = new AtomicLong(0);
    
    // 用于统计本次批处理中实际检测到的违规数量
    private final AtomicLong currentBatchViolationsCount = new AtomicLong(0);

    // ========== 核心违规检测方法 ==========

    @EventListener
    public void handleRuleViolationEventOccurred(RuleViolationEventOccurred event) {
        currentBatchViolationsCount.incrementAndGet();
        log.debug("事件监听器收到 RuleViolationEventOccurred，当前批次违规数: {}", currentBatchViolationsCount.get());
    }

    @Override
    public List<RuleViolationEvent> detectViolations(VehicleLocation vehicleLocation) {
        if (!isRealTimeDetectionEnabled()) {
            log.debug("实时违规检测已禁用: vehicleId={}", vehicleLocation.getVehicleId());
            return new ArrayList<>();
        }

        long startTime = System.currentTimeMillis();
        
        try {
            log.debug("开始实时违规检测: vehicleId={}", 
                     vehicleLocation.getVehicleId());

            // 查询适用的规则
            List<SpatialRule> applicableRules = locationRuleQueryService.findApplicableRules(
                vehicleLocation.getLocation(), 
                vehicleLocation.getVehicleType(), 
                vehicleLocation.getTimestamp()
            );

            if (applicableRules.isEmpty()) {
                log.debug("无适用规则，跳过违规检测: vehicleId={}", vehicleLocation.getVehicleId());
                return new ArrayList<>();
            }

            // 检测违规
            // RuleViolationEvent将通过事件监听器处理和统计，此处不再收集列表
            Map<String, Object> vehicleState = buildVehicleStateMap(vehicleLocation);

            for (SpatialRule rule : applicableRules) {
                try {
                    ruleExecutionEngine.detectViolation(
                        rule,
                        String.valueOf(vehicleLocation.getVehicleId()), // 将Long转换为String
                        vehicleLocation.getVehicleType(),
                        vehicleLocation.getLocation(),
                        vehicleState,
                        vehicleLocation.getTimestamp()
                    );

                    // RuleViolationEventOccurred事件由 RuleExecutionEngineImpl 内部发布，
                    // 并由本类的 @EventListener 方法负责计数和处理。
                    // 因此，此处不再需要 `violations.add(violation);`

                } catch (Exception e) {
                    log.error("规则违规检测失败: vehicleId={}, ruleId={}", 
                             vehicleLocation.getVehicleId(), rule.getRuleId(), e);
                }
            }

            // 违规事件将由 @EventListener 监听器自动处理，这里不需要手动调用 processBatchViolationEvents
            // processBatchViolationEvents(violations);

            // 更新性能指标
            updateMetrics(startTime, 0); // 这里的violations.size()将不再有效，但totalViolations由EventListener更新
            
            log.debug("违规检测完成: vehicleId={}", 
                     vehicleLocation.getVehicleId());

            return new ArrayList<>(); // 返回空列表，因为实际违规通过事件监听器处理

        } catch (Exception e) {
            log.error("实时违规检测失败: vehicleId={}, detectionId={}", 
                     vehicleLocation.getVehicleId(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<RuleViolationEvent> detectBatchViolations(List<VehicleLocation> vehicleLocations) {
        if (!isRealTimeDetectionEnabled()) {
            log.debug("实时违规检测已禁用，跳过批量检测");
            return new ArrayList<>();
        }

        // 在每次批量检测开始前，重置计数器
        currentBatchViolationsCount.set(0);

        log.info("开始批量违规检测: 车辆数量={}", vehicleLocations.size());
        
        // 不再需要 allViolations 列表，通过事件监听器进行统计
        // List<RuleViolationEvent> allViolations = new ArrayList<>();
        
        for (VehicleLocation vehicleLocation : vehicleLocations) {
            try {
                // 调用 detectViolations，它会发布 RuleViolationEventOccurred 事件
                detectViolations(vehicleLocation);
                // allViolations.addAll(violations); // 不再需要收集列表
            } catch (Exception e) {
                log.error("批量违规检测中单个车辆处理失败: vehicleId={}", 
                         vehicleLocation.getVehicleId(), e);
            }
        }
        
        log.info("批量违规检测完成: 处理车辆{}个，检测到违规{}个", 
                vehicleLocations.size(), currentBatchViolationsCount.get()); // 使用监听器统计的违规数
        log.debug("RealTimeViolationDetectorImpl - 批量检测结束，最终计数: {}", currentBatchViolationsCount.get());
        
        return new ArrayList<>(); // 返回空列表，因为实际违规通过事件监听器处理
    }

    @Override
    public RuleViolationEvent detectRuleViolation(VehicleLocation vehicleLocation, SpatialRule rule) {
        try {
            Map<String, Object> vehicleState = buildVehicleStateMap(vehicleLocation);
            
            return ruleExecutionEngine.detectViolation(
                rule,
                String.valueOf(vehicleLocation.getVehicleId()), // 将Long转换为String
                vehicleLocation.getVehicleType(),
                vehicleLocation.getLocation(),
                vehicleState,
                vehicleLocation.getTimestamp()
            );
        } catch (Exception e) {
            log.error("单个规则违规检测失败: vehicleId={}, ruleId={}", 
                     vehicleLocation.getVehicleId(), rule.getRuleId(), e);
            return null;
        }
    }

    @Override
    public List<RuleViolationEvent> detectLocationViolations(String vehicleId, MovingObjectType vehicleType,
                                                            Point location, Map<String, Object> vehicleState, 
                                                            LocalDateTime timestamp) {
        try {
            return ruleExecutionEngine.detectAllViolations(vehicleId, vehicleType, location, vehicleState, timestamp);
        } catch (Exception e) {
            log.error("位置违规检测失败: vehicleId={}, location=({}, {})", 
                     vehicleId, location.getX(), location.getY(), e);
            return new ArrayList<>();
        }
    }

    // ========== 违规事件处理方法 ==========

    @Override
    public void processViolationEvent(RuleViolationEvent violationEvent) {
        try {
            long startTime = System.currentTimeMillis();
            
            // 评估违规严重程度
            int severity = assessViolationSeverity(violationEvent);
            // 简化版本：不修改违规类型，保持原有值
            
            // 检查是否为重复违规
            boolean isDuplicate = isDuplicateViolation(
                violationEvent.getVehicleId(), 
                violationEvent.getRuleName(), 
                violationEvent.getViolationType(),
                5 // 5分钟内的重复违规
            );
            
            if (isDuplicate) {
                log.debug("跳过重复违规: vehicleId={}, ruleId={}", 
                         violationEvent.getVehicleId(), violationEvent.getRuleName());
                return;
            }
            
            // 使用违规事件处理器处理
            ruleViolationProcessor.processViolationEvent(violationEvent);
            
            // 如果是高严重性违规，立即处理
            if (severity >= 8) {
                processCriticalViolation(violationEvent);
            }
            
            // 记录处理历史
            long processingTime = System.currentTimeMillis() - startTime;
            recordViolationProcessingHistory(violationEvent, "SUCCESS", processingTime);
            
        } catch (Exception e) {
            log.error("违规事件处理失败: id={}", violationEvent.getId(), e);
            recordViolationProcessingHistory(violationEvent, "ERROR", 0);
        }
    }

    @Override
    public void processBatchViolationEvents(List<RuleViolationEvent> violationEvents) {
        log.info("开始批量处理违规事件: 数量={}", violationEvents.size());
        
        for (RuleViolationEvent violationEvent : violationEvents) {
            try {
                processViolationEvent(violationEvent);
            } catch (Exception e) {
                log.error("批量违规事件处理中单个事件失败: eventId={}", 
                         violationEvent.getId(), e);
            }
        }
        
        log.info("批量违规事件处理完成: 处理数量={}", violationEvents.size());
    }

    // 异步方法已移除 - 改为同步处理以简化架构

    @Override
    public void processCriticalViolation(RuleViolationEvent violationEvent) {
        try {
            log.warn("处理高严重性违规事件: eventId={}, vehicleId={}, violationType={}", 
                    violationEvent.getId(), violationEvent.getVehicleId(), 
                    violationEvent.getViolationType());
            
            // 立即发送告警通知
            sendViolationAlert(violationEvent);
            
            // 执行紧急响应动作
            Map<String, Object> emergencyActions = new HashMap<>();
            emergencyActions.put("immediate_alert", true);
            emergencyActions.put("escalate_to_control", true);
            emergencyActions.put("priority", "CRITICAL");
            
            executeViolationResponse(violationEvent, emergencyActions);
            
        } catch (Exception e) {
            log.error("高严重性违规事件处理失败: id={}", violationEvent.getId(), e);
        }
    }


    @Override
    public RuleAlertLevel determineAlertLevel(ViolationType violationType, SpatialRule rule, 
                                                 Map<String, Object> vehicleState) {
        // 根据违规类型确定基础告警级别
        RuleAlertLevel baseLevel = getDefaultAlertLevel(violationType);
        
        // 根据规则类别调整告警级别
        if (rule.getCategory() == RuleCategory.ACCESS_CONTROL || 
            rule.getCategory() == RuleCategory.SAFETY_ZONE) {
            // 准入控制和安全区域违规提升告警级别
            if (baseLevel == RuleAlertLevel.WARNING) {
                return RuleAlertLevel.CRITICAL;
            } else if (baseLevel == RuleAlertLevel.INFO) {
                return RuleAlertLevel.WARNING;
            }
        }
        
        return baseLevel;
    }

    public boolean isDuplicateViolation(Long vehicleId, String ruleName, String violationType, int timeWindow) {
        try {
            LocalDateTime since = LocalDateTime.now().minusMinutes(timeWindow);
            // 简化版本：使用findAll然后过滤检查重复违规
            return violationEventRepository.findAll()
                    .stream()
                    .anyMatch(event -> vehicleId.equals(event.getVehicleId()) 
                             && ruleName.equals(event.getRuleName())
                             && violationType.equals(event.getViolationType())
                             && event.getViolationTime() != null
                             && event.getViolationTime().isAfter(since));
        } catch (Exception e) {
            log.error("检查重复违规失败: vehicleId={}, ruleName={}", vehicleId, ruleName, e);
            return false; // 出错时不认为是重复违规，避免漏检
        }
    }

    // ========== 违规响应和通知 ==========

    @Override
    public void sendViolationAlert(RuleViolationEvent violationEvent) {
        try {
            log.info("发送违规告警通知: eventId={}, vehicleId={}, alertLevel={}", 
                    violationEvent.getId(), violationEvent.getVehicleId(), 
                    violationEvent.getViolationType());
            
            // TODO: 集成WebSocket推送
            // TODO: 集成邮件/短信通知
            // TODO: 集成控制系统通知
            
        } catch (Exception e) {
            log.error("发送违规告警通知失败: id={}", violationEvent.getId(), e);
        }
    }

    @Override
    public void executeViolationResponse(RuleViolationEvent violationEvent, Map<String, Object> responseActions) {
        try {
            log.info("执行违规响应动作: eventId={}, actions={}", 
                    violationEvent.getId(), responseActions);
            
            // TODO: 实现具体的响应动作
            
        } catch (Exception e) {
            log.error("执行违规响应动作失败: id={}", violationEvent.getId(), e);
        }
    }

    @Override
    public void recordViolationProcessingHistory(RuleViolationEvent violationEvent, String processingResult, 
                                               long responseTime) {
        try {
            log.debug("记录违规处理历史: eventId={}, result={}, responseTime={}ms", 
                     violationEvent.getId(), processingResult, responseTime);
        } catch (Exception e) {
            log.error("记录违规处理历史失败: id={}", violationEvent.getId(), e);
        }
    }

    // ========== 违规统计和分析 ==========

    @Override
    public Map<String, Object> getVehicleViolationStatistics(Long vehicleId, LocalDateTime startTime, 
                                                            LocalDateTime endTime) {
        Map<String, Object> stats = new HashMap<>();
        stats.put("vehicleId", vehicleId);
        stats.put("totalViolations", 0);
        stats.put("violationTypes", new HashMap<>());
        return stats;
    }

    @Override
    public Map<String, Object> getRuleViolationStatistics(String ruleId, LocalDateTime startTime, 
                                                         LocalDateTime endTime) {
        Map<String, Object> stats = new HashMap<>();
        stats.put("ruleId", ruleId);
        stats.put("totalViolations", 0);
        stats.put("vehicleBreakdown", new HashMap<>());
        return stats;
    }

    @Override
    public List<Map<String, Object>> getViolationHotspots(int timeWindow) {
        return new ArrayList<>();
    }

    @Override
    public List<Map<String, Object>> getViolationTrends(LocalDateTime startTime, LocalDateTime endTime, 
                                                       String granularity) {
        return new ArrayList<>();
    }

    // ========== 检测配置和优化 ==========

    @Override
    public void configureViolationDetection(Map<String, Object> config) {
        this.detectionConfig.putAll(config);
        log.info("更新违规检测配置: {}", config);
    }

    @Override
    public Map<String, Object> getDetectionMetrics() {
        Map<String, Object> metrics = new HashMap<>();
        metrics.put("totalDetections", totalDetections.get());
        metrics.put("totalViolations", totalViolations.get());
        metrics.put("averageProcessingTime", calculateAverageProcessingTime());
        metrics.put("violationRate", calculateViolationRate());
        metrics.put("realTimeDetectionEnabled", realTimeDetectionEnabled.get());
        return metrics;
    }

    @Override
    public void setRealTimeDetectionEnabled(boolean enabled) {
        realTimeDetectionEnabled.set(enabled);
        log.info("实时违规检测状态变更: enabled={}", enabled);
    }

    @Override
    public boolean isRealTimeDetectionEnabled() {
        return realTimeDetectionEnabled.get();
    }

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

    private Map<String, Object> buildVehicleStateMap(VehicleLocation vehicleLocation) {
        Map<String, Object> vehicleState = new HashMap<>();
        
        vehicleState.put("vehicleId", vehicleLocation.getVehicleId());
        vehicleState.put("vehicleType", vehicleLocation.getVehicleType());
        vehicleState.put("timestamp", vehicleLocation.getTimestamp());
        vehicleState.put("vehicleLicense", vehicleLocation.getLicensePlate()); // 添加车牌号
        
        if (vehicleLocation.getLocation() != null) {
            vehicleState.put("longitude", vehicleLocation.getLocation().getX());
            vehicleState.put("latitude", vehicleLocation.getLocation().getY());
        }
        
        if (vehicleLocation.getAltitude() != null) {
            vehicleState.put("altitude", vehicleLocation.getAltitude());
        }
        
        if (vehicleLocation.getHeading() != null) {
            vehicleState.put("heading", vehicleLocation.getHeading());
        }
        
        if (vehicleLocation.getSpeed() != null) {
            vehicleState.put("speed", vehicleLocation.getSpeed());
        }
        
        return vehicleState;
    }

    private void updateMetrics(long startTime, int violationCount) {
        totalDetections.incrementAndGet();
        totalViolations.addAndGet(violationCount);
        totalProcessingTime.addAndGet(System.currentTimeMillis() - startTime);
    }

    private double calculateAverageProcessingTime() {
        long detections = totalDetections.get();
        return detections > 0 ? (double) totalProcessingTime.get() / detections : 0.0;
    }

    private double calculateViolationRate() {
        long detections = totalDetections.get();
        return detections > 0 ? (double) totalViolations.get() / detections : 0.0;
    }

    /**
     * 根据违规类型获取默认告警级别
     * @param violationType 违规类型
     * @return 默认告警级别
     */
    private RuleAlertLevel getDefaultAlertLevel(ViolationType violationType) {
        switch (violationType) {
            case SAFETY_ZONE:
            case ACCESS:
                return RuleAlertLevel.CRITICAL;
            case PRIORITY:
            case VEHICLE_TYPE:
                return RuleAlertLevel.WARNING;
            case SPEED:
            case HEIGHT:
            case WEIGHT:
            case TIME_RESTRICTION:
                return RuleAlertLevel.WARNING;
            case DWELL_TIME:
            case PATH_DEVIATION:
            case OTHER:
            default:
                return RuleAlertLevel.INFO;
        }
    }

    /**
     * 评估违规严重程度
     * @param violationEvent 违规事件
     * @return 严重程度评分（1-10）
     */
    @Override
    public int assessViolationSeverity(RuleViolationEvent violationEvent) {
        // 简化版本：根据违规类型返回默认严重程度
        String violationType = violationEvent.getViolationType();
        if (violationType == null) {
            return 1;
        }
        
        switch (violationType) {
            case "ACCESS":
                return 8;
            case "SPEED":
                return 6;
            case "HEIGHT":
            case "WEIGHT":
                return 5;
            default:
                return 3;
        }
    }

    /**
     * 检查是否为重复违规（接口要求的签名）
     * @param vehicleId 车辆ID
     * @param ruleName 规则名称
     * @param violationType 违规类型
     * @param timeWindow 时间窗口（分钟）
     * @return 如果是重复违规返回true
     */
    @Override
    public boolean isDuplicateViolation(Long vehicleId, String ruleName, ViolationType violationType, int timeWindow) {
        // 调用我们的简化版本
        return isDuplicateViolation(vehicleId, ruleName, violationType.name(), timeWindow);
    }
} 