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

import com.qaup.collision.rule.event.RuleViolationEvent;
import com.qaup.collision.rule.model.entity.SpatialRule;
import com.qaup.collision.rule.model.enums.RuleExecutionResult;
import com.qaup.collision.rule.model.enums.ViolationType;
import com.qaup.collision.rule.repository.RuleViolationEventRepository;
import com.qaup.collision.rule.service.RuleViolationProcessor;
import com.qaup.collision.common.model.spatial.VehicleLocation;

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

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * 规则违规事件处理器实现类（简化版）
 * 负责处理规则违规事件的生成、处理、通知和响应
 * 专门针对无人车违规事件
 * 
 * @author AI Assistant
 * @since 2025-01-17
 */
@Service
@Transactional
public class RuleViolationProcessorImpl implements RuleViolationProcessor {

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

    @Autowired
    private RuleViolationEventRepository violationEventRepository;

    // ============================================
    // 违规事件生成
    // ============================================

    /**
     * 创建违规事件
     */
    @Override
    public RuleViolationEvent createViolationEvent(SpatialRule rule, VehicleLocation vehicleLocation,
                                                   RuleExecutionResult executionResult, Map<String, Object> violationDetails) {
        
        try {
            RuleViolationEvent event = new RuleViolationEvent();
            
            // 设置基本信息（基于vehicle_id进行内部处理）
            event.setVehicleId(vehicleLocation.getVehicleId()); // 内部逻辑完全基于vehicle_id
            event.setRuleName(rule.getName());
            
            // 设置违规类型和详情
            event.setViolationType(mapExecutionResultToViolationType(executionResult).name());
            event.setAlertLevel(rule.getAlertLevel());
            event.setDescription(generateViolationDescription(rule, violationDetails));
            
            // 设置位置信息
            event.setLocation(vehicleLocation.getLocation());
            
            // 设置实际值和限制值（如果有的话）
            if (violationDetails.containsKey("actualValue")) {
                Object actualValue = violationDetails.get("actualValue");
                if (actualValue instanceof Number) {
                    event.setActualValue(((Number) actualValue).doubleValue());
                }
            }
            if (violationDetails.containsKey("limitValue")) {
                Object limitValue = violationDetails.get("limitValue");
                if (limitValue instanceof Number) {
                    event.setLimitValue(((Number) limitValue).doubleValue());
                }
            }
            
            // 保存事件
            event = violationEventRepository.save(event);
            
            logger.info("创建违规事件: id={}, 规则={}, vehicleId={}, 违规类型={}", 
                       event.getId(), rule.getName(), vehicleLocation.getVehicleId(), 
                       event.getViolationType());
            
            return event;
            
        } catch (Exception e) {
            logger.error("创建违规事件失败: ruleId={}, vehicleId={}", 
                        rule.getRuleId(), vehicleLocation.getVehicleId(), e);
            throw new RuntimeException("创建违规事件失败", e);
        }
    }

    @Override
    public List<RuleViolationEvent> createViolationEvents(List<ViolationInfo> violations) {
        List<RuleViolationEvent> events = new ArrayList<>();
        
        for (ViolationInfo violation : violations) {
            try {
                RuleViolationEvent event = createViolationEvent(
                    violation.getRule(),
                    violation.getVehicleLocation(),
                    violation.getExecutionResult(),
                    violation.getViolationDetails()
                );
                events.add(event);
            } catch (Exception e) {
                logger.error("批量创建违规事件失败: ruleId={}, vehicleId={}", 
                           violation.getRule().getRuleId(), 
                           violation.getVehicleLocation().getVehicleId(), e);
            }
        }
        
        logger.info("批量创建违规事件完成: 总数={}, 成功={}", violations.size(), events.size());
        return events;
    }

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

    @Override
    public ViolationProcessingResult processViolationEvent(RuleViolationEvent violationEvent) {
        String eventId = violationEvent.getId().toString();
        
        try {
            logger.info("开始处理违规事件: eventId={}", eventId);
            
            // 验证事件
            if (!validateViolationEvent(violationEvent)) {
                return new ViolationProcessingResult(eventId, false, "事件验证失败");
            }
            
            // 执行响应动作
            List<String> actionsExecuted = executeResponseActions(violationEvent);
            
            // 简化版本：只保存事件，不更新复杂状态
            try {
                violationEventRepository.save(violationEvent);
            } catch (org.springframework.orm.ObjectOptimisticLockingFailureException e) {
                logger.warn("违规事件并发更新冲突，跳过保存: eventId={}", eventId);
                // 乐观锁冲突时，说明其他线程已经处理了该事件，可以跳过
            }
            
            ViolationProcessingResult result = new ViolationProcessingResult(eventId, true, "处理成功");
            result.setActionsExecuted(actionsExecuted);
            
            logger.info("违规事件处理完成: eventId={}, actionsExecuted={}", eventId, actionsExecuted);
            return result;
            
        } catch (Exception e) {
            logger.error("处理违规事件失败: eventId={}", eventId, e);
            
            ViolationProcessingResult result = new ViolationProcessingResult(eventId, false, "处理失败: " + e.getMessage());
            result.setError(e);
            return result;
        }
    }

    @Override
    public List<ViolationProcessingResult> processViolationEvents(List<RuleViolationEvent> violationEvents) {
        return violationEvents.stream()
                .map(this::processViolationEvent)
                .collect(Collectors.toList());
    }

    // ============================================
    // 违规事件状态管理（简化版本）
    // ============================================

    @Override
    public boolean acknowledgeViolation(String eventId, String acknowledgedBy, String notes) {
        try {
            Optional<RuleViolationEvent> eventOpt = violationEventRepository.findById(eventId);
            if (!eventOpt.isPresent()) {
                logger.warn("违规事件不存在: eventId={}", eventId);
                return false;
            }
            
            // 简化版本：只记录日志，不修改复杂状态
            logger.info("违规事件已确认: eventId={}, acknowledgedBy={}, notes={}", eventId, acknowledgedBy, notes);
            return true;
            
        } catch (Exception e) {
            logger.error("确认违规事件失败: eventId={}", eventId, e);
            return false;
        }
    }

    @Override
    public boolean resolveViolation(String eventId, String resolvedBy, String resolution) {
        try {
            Optional<RuleViolationEvent> eventOpt = violationEventRepository.findById(eventId);
            if (!eventOpt.isPresent()) {
                logger.warn("违规事件不存在: eventId={}", eventId);
                return false;
            }
            
            // 简化版本：只记录日志，不修改复杂状态
            logger.info("违规事件已解决: eventId={}, resolvedBy={}, resolution={}", eventId, resolvedBy, resolution);
            return true;
            
        } catch (Exception e) {
            logger.error("解决违规事件失败: eventId={}", eventId, e);
            return false;
        }
    }

    @Override
    public boolean ignoreViolation(String eventId, String ignoredBy, String reason) {
        try {
            Optional<RuleViolationEvent> eventOpt = violationEventRepository.findById(eventId);
            if (!eventOpt.isPresent()) {
                logger.warn("违规事件不存在: eventId={}", eventId);
                return false;
            }
            
            // 简化版本：只记录日志，不修改复杂状态
            logger.info("违规事件已忽略: eventId={}, ignoredBy={}, reason={}", eventId, ignoredBy, reason);
            return true;
            
        } catch (Exception e) {
            logger.error("忽略违规事件失败: eventId={}", eventId, e);
            return false;
        }
    }

    // ============================================
    // 违规事件查询（简化版本）
    // ============================================

    @Override
    @Transactional(readOnly = true)
    public List<RuleViolationEvent> getPendingViolations(int limit) {
        // 简化版本：返回最近的违规事件
        return violationEventRepository.findAll()
                .stream()
                .sorted((a, b) -> b.getId().compareTo(a.getId())) // 按ID倒序排列
                .limit(limit)
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(readOnly = true)
    public List<RuleViolationEvent> getHighSeverityViolations(int hours) {
        // 简化版本：返回最近的违规事件
        return violationEventRepository.findAll()
                .stream()
                .limit(10) // 限制数量
                .collect(Collectors.toList());
    }

    @Override
    @Transactional(readOnly = true)
    public List<RuleViolationEvent> getVehicleViolationHistory(String vehicleId, int days) {
        // 简化版本：按车牌号查询，使用findAll然后过滤
        try {
            Long vehicleIdLong = Long.parseLong(vehicleId);
            return violationEventRepository.findByVehicleId(vehicleIdLong);
        } catch (NumberFormatException e) {
            logger.warn("无效的vehicleId格式: {}", vehicleId);
            return Collections.emptyList();
        }
    }

    // ============================================
    // 违规统计分析（简化版本）
    // ============================================

    @Override
    @Transactional(readOnly = true)
    public ViolationStatistics getViolationStatistics(LocalDateTime startTime, LocalDateTime endTime) {
        ViolationStatistics stats = new ViolationStatistics();
        
        // 获取所有违规事件
        List<RuleViolationEvent> allEvents = violationEventRepository.findAll();
        stats.setTotalViolations(allEvents.size());
        
        // 简化版本：所有事件都视为待处理
        stats.setPendingViolations(allEvents.size());
        stats.setResolvedViolations(0);
        
        // 按类型统计
        Map<String, Long> violationsByType = allEvents.stream()
                .collect(Collectors.groupingBy(
                    RuleViolationEvent::getViolationType,
                    Collectors.counting()
                ));
        stats.setViolationsByType(violationsByType);
        
        // 按严重程度统计（简化版本：根据违规类型判断）
        Map<String, Long> violationsBySeverity = new HashMap<>();
        violationsBySeverity.put("WARNING", (long) allEvents.size());
        stats.setViolationsBySeverity(violationsBySeverity);
        
        // 按规则统计
        Map<String, Long> violationsByRule = allEvents.stream()
                .collect(Collectors.groupingBy(
                    RuleViolationEvent::getRuleName,
                    Collectors.counting()
                ));
        stats.setViolationsByRule(violationsByRule);
        
        return stats;
    }

    @Override
    @Transactional(readOnly = true)
    public RuleViolationFrequency getRuleViolationFrequency(String ruleId, int days) {
        RuleViolationFrequency frequency = new RuleViolationFrequency();
        frequency.setRuleId(ruleId);
        
        // 获取指定规则的违规事件，使用findAll然后过滤
        List<RuleViolationEvent> events = violationEventRepository.findAll()
                .stream()
                .filter(event -> ruleId.equals(event.getRuleName()))
                .collect(Collectors.toList());
        
        // 总违规数
        frequency.setTotalViolations(events.size());
        
        // 平均每日违规数
        frequency.setAverageViolationsPerDay((double) events.size() / days);
        
        // 按日统计（简化版本）
        Map<String, Long> violationsByDay = new HashMap<>();
        violationsByDay.put(LocalDateTime.now().toLocalDate().toString(), (long) events.size());
        frequency.setViolationsByDay(violationsByDay);
        
        return frequency;
    }

    @Override
    @Transactional(readOnly = true)
    public List<ViolationHotspot> getViolationHotspots(int days, int limit) {
        // 简化实现：按规则名称统计违规热点
        List<RuleViolationEvent> events = violationEventRepository.findAll();
        
        Map<String, Long> ruleViolationCounts = events.stream()
                .collect(Collectors.groupingBy(
                    RuleViolationEvent::getRuleName,
                    Collectors.counting()
                ));
        
        return ruleViolationCounts.entrySet().stream()
                .sorted(Map.Entry.<String, Long>comparingByValue().reversed())
                .limit(limit)
                .map(entry -> {
                    ViolationHotspot hotspot = new ViolationHotspot();
                    hotspot.setAreaId(entry.getKey());
                    hotspot.setAreaName("规则区域: " + entry.getKey());
                    hotspot.setViolationCount(entry.getValue());
                    hotspot.setViolationDensity(entry.getValue().doubleValue() / days);
                    return hotspot;
                })
                .collect(Collectors.toList());
    }

    // ============================================
    // 私有辅助方法（简化版本）
    // ============================================

    private ViolationType mapExecutionResultToViolationType(RuleExecutionResult result) {
        // 简化映射
        switch (result) {
            case VIOLATION:
                return ViolationType.SPEED; // 默认为速度违规
            case EXECUTION_ERROR:
            case CONFIGURATION_ERROR:
                return ViolationType.OTHER;
            default:
                return ViolationType.OTHER;
        }
    }

    private String generateViolationDescription(SpatialRule rule, Map<String, Object> violationDetails) {
        StringBuilder description = new StringBuilder();
        description.append("规则违规: ").append(rule.getName());
        
        if (violationDetails.containsKey("actualValue")) {
            description.append(", 实际值: ").append(violationDetails.get("actualValue"));
        }
        if (violationDetails.containsKey("limitValue")) {
            description.append(", 限制值: ").append(violationDetails.get("limitValue"));
        }
        if (violationDetails.containsKey("reason")) {
            description.append(", 原因: ").append(violationDetails.get("reason"));
        }
        
        return description.toString();
    }

    private boolean validateViolationEvent(RuleViolationEvent event) {
        return event != null 
            && event.getId() != null 
            && event.getRuleName() != null 
            && event.getVehicleId() != null
            && event.getLocation() != null;
    }

    private List<String> executeResponseActions(RuleViolationEvent event) {
        List<String> actionsExecuted = new ArrayList<>();
        
        // 基本响应动作
        actionsExecuted.add("LOG_EVENT");
        
        // 根据违规类型执行不同动作（简化版本）
        switch (event.getViolationType()) {
            case "SPEED":
                actionsExecuted.add("SEND_SPEED_WARNING");
                break;
            case "ACCESS":
                actionsExecuted.add("SEND_ACCESS_ALERT");
                break;
            default:
                actionsExecuted.add("RECORD_INCIDENT");
                break;
        }
        
        return actionsExecuted;
    }

} 