package com.qaup.collision.websocket.broadcaster;

import com.qaup.collision.rule.event.RuleExecutionEvent;
import com.qaup.collision.rule.event.RuleStateChangeEvent;
import com.qaup.collision.rule.event.RuleViolationEvent;
import com.qaup.collision.rule.event.RuleViolationEventOccurred;
import com.qaup.collision.rule.model.entity.SpatialRule;
import com.qaup.collision.rule.model.enums.RuleExecutionResult;
import com.qaup.collision.websocket.event.RuleExecutionStatusWebSocketEvent;
import com.qaup.collision.websocket.event.RuleStateChangeWebSocketEvent;
import com.qaup.collision.websocket.event.RuleViolationWebSocketEvent;
import com.qaup.collision.websocket.event.PathConflictAlertWebSocketEvent;
import com.qaup.collision.websocket.message.RuleExecutionStatusPayload;
import com.qaup.collision.websocket.message.RuleStateChangePayload;
import com.qaup.collision.websocket.message.RuleViolationPayload;
import com.qaup.collision.websocket.message.PathConflictAlertMessage;
import com.qaup.collision.common.adapter.QuapDataAdapter;
import com.qaup.system.domain.SysVehicleInfo; 
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional; // 导入 Optional

/**
 * 规则事件WebSocket发布服务（简化版）
 * 监听内部规则事件，转换为WebSocket事件并发布到前端
 * 专门针对无人车违规事件
 * 
 * @author AI Assistant
 * @since 2025-01-17
 */
@Service
public class RuleEventWebSocketPublisher {

    private static final Logger logger = LoggerFactory.getLogger(RuleEventWebSocketPublisher.class);
    
    private final ApplicationEventPublisher eventPublisher;
    private final QuapDataAdapter quapDataAdapter; 

    // 构造函数中初始化ObjectMapper
    public RuleEventWebSocketPublisher(ApplicationEventPublisher eventPublisher, QuapDataAdapter quapDataAdapter) {
        this.eventPublisher = eventPublisher;
        this.quapDataAdapter = quapDataAdapter;
    }

    /**
     * 监听规则违规事件，转换为WebSocket事件
     * 
     * @param event 规则违规事件
     */
    @EventListener
    public void handleRuleViolationEvent(RuleViolationEventOccurred event) {
        try {
            RuleViolationEvent violationEvent = event.getViolationEvent();
            
            // 动态查询车牌号（基于vehicle_id）
            String licensePlate = getLicensePlateByVehicleId(violationEvent.getVehicleId());
            
            // 构建简化的WebSocket载荷（只保留前端需要的核心字段）
            RuleViolationPayload payload = RuleViolationPayload.builder()
                    .vehicleType("UNMANNED_VEHICLE") // 项目只管理无人车
                    .vehicleLicense(licensePlate) // 动态查询的车牌号
                    .ruleName(violationEvent.getRuleName())
                    .violationType(violationEvent.getViolationType().toString())
                    .actualValue(violationEvent.getActualValue())
                    .limitValue(violationEvent.getLimitValue())
                    .alertLevel(determineAlertLevel(violationEvent))
                    .position(violationEvent.getLocation() != null ? 
                              RuleViolationPayload.Position.builder()
                                  .latitude(violationEvent.getLocation().getY())
                                  .longitude(violationEvent.getLocation().getX())
                                  .build() : null) // 设置位置对象
                    .description(violationEvent.getDescription())
                    .requiresImmediateResponse(requiresImmediateResponse(violationEvent))
                    .isCritical(isCriticalViolation(violationEvent))
                    .recommendedAction(getRecommendedAction(violationEvent))
                    .status("PENDING") // 简化版本中统一为PENDING
                    .build();

            // 发布WebSocket事件
            RuleViolationWebSocketEvent webSocketEvent = RuleViolationWebSocketEvent.create(payload);
            eventPublisher.publishEvent(webSocketEvent);

            logger.debug("Published rule violation WebSocket event for vehicleId {} (license: {}) and rule {}", 
                         violationEvent.getVehicleId(), licensePlate, violationEvent.getRuleName());

        } catch (Exception e) {
            logger.error("Failed to publish rule violation WebSocket event", e);
        }
    }

    /**
     * 监听规则执行事件，转换为WebSocket事件
     * 
     * @param event 规则执行事件
     */
    @EventListener
    public void handleRuleExecutionEvent(RuleExecutionEvent event) {
        try {
            // 构建WebSocket载荷
            RuleExecutionStatusPayload payload = RuleExecutionStatusPayload.builder()
                    .ruleId(event.getRule().getRuleId())
                    .ruleName(event.getRule().getName())
                    .vehicleId(event.getVehicleId())
                    .vehicleType(getVehicleTypeFromContext(event.getExecutionContext())) // 从context中获取vehicleType
                    .eventType(event.getEventType() != null ? event.getEventType().name() : "UNKNOWN")
                    .executionStatus(event.getExecutionStatus() != null ? event.getExecutionStatus().name() : "UNKNOWN")
                    .executionResult(event.getExecutionResult() != null ? event.getExecutionResult().name() : "UNKNOWN")
                    .startTime(event.getExecutionStartTime())
                    .endTime(event.getExecutionEndTime())
                    .durationMs(event.getExecutionDurationMs())
                    .location(null) // RuleExecutionEvent中没有location信息
                    .longitude(null)
                    .latitude(null)
                    .isSuccess(event.isExecutionSuccessful())
                    .isViolation(event.getExecutionResult() != null && event.getExecutionResult().name().contains("VIOLATION"))
                    .errorMessage(event.getErrorMessage())
                    .executionDetails(event.getExecutionDetails())
                    .ruleCategory(event.getRule().getCategory() != null ? event.getRule().getCategory().name() : "UNKNOWN")
                    .requiresAction(event.getExecutionResult() != null && event.getExecutionResult() != RuleExecutionResult.PASS)
                    .context(event.getExecutionContext())
                    .performanceMetrics(createPerformanceMetrics(event))
                    .build();

            // 发布WebSocket事件
            RuleExecutionStatusWebSocketEvent webSocketEvent = RuleExecutionStatusWebSocketEvent.create(payload);
            eventPublisher.publishEvent(webSocketEvent);

            logger.debug("Published rule execution WebSocket event for vehicle {} and rule {}", 
                         event.getVehicleId(), event.getRule().getRuleId());

        } catch (Exception e) {
            logger.error("Failed to publish rule execution WebSocket event", e);
        }
    }

    /**
     * 监听规则状态变更事件，转换为WebSocket事件
     * 
     * @param event 规则状态变更事件
     */
    @EventListener
    public void handleRuleStateChangeEvent(RuleStateChangeEvent event) {
        try {
            SpatialRule rule = event.getRule();
            
            // 构建WebSocket载荷
            RuleStateChangePayload payload = RuleStateChangePayload.builder()
                    .ruleId(rule.getRuleId())
                    .ruleName(rule.getName())
                    .ruleCategory(rule.getCategory() != null ? rule.getCategory().name() : "UNKNOWN")
                    .changeType(event.getChangeType() != null ? event.getChangeType().name() : "UNKNOWN")
                    .fromStatus(event.getPreviousStatus() != null ? event.getPreviousStatus().name() : "UNKNOWN")
                    .toStatus(event.getNewStatus() != null ? event.getNewStatus().name() : "UNKNOWN")
                    .changeTime(event.getChangeTimestamp())
                    .reason(event.getChangeReason())
                    .changedBy(event.getChangedBy())
                    .affectsRuntime(event.isAffectsRuntime())
                    .severityScore(event.getChangeSeverity())
                    .requiresNotification(event.requiresNotification())
                    .impactScope(determineImpactScope(event))
                    .description(event.getEventDescription())
                    .configChanges(event.getChangeContext())
                    .effectiveTime(LocalDateTime.now())
                    .expiryTime(rule.getEffectiveEndTime())
                    .context(event.getChangeContext())
                    .rollbackInfo(createRollbackInfo(event))
                    .notificationLevel(determineNotificationLevel(event))
                    .build();

            // 发布WebSocket事件
            RuleStateChangeWebSocketEvent webSocketEvent = RuleStateChangeWebSocketEvent.create(payload);
            eventPublisher.publishEvent(webSocketEvent);

            logger.debug("Published rule state change WebSocket event for rule {}", rule.getRuleId());

        } catch (Exception e) {
            logger.error("Failed to publish rule state change WebSocket event", e);
        }
    }

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

    /**
     * 确定告警级别（基于违规类型）
     */
    private String determineAlertLevel(RuleViolationEvent violationEvent) {
        switch (violationEvent.getViolationType().toString()) {
            case "SPEED":
                return "WARNING";
            case "ACCESS":
                return "CRITICAL";
            case "HEIGHT":
            case "WEIGHT":
                return "WARNING";
            case "OTHER":
            default:
                return "INFO";
        }
    }

    /**
     * 判断是否需要立即响应
     */
    private Boolean requiresImmediateResponse(RuleViolationEvent violationEvent) {
        return "ACCESS".equals(violationEvent.getViolationType().toString()) ||
               "CRITICAL".equals(determineAlertLevel(violationEvent));
    }

    /**
     * 判断是否为紧急违规（简化版本）
     */
    private Boolean isCriticalViolation(RuleViolationEvent violationEvent) {
        String alertLevel = determineAlertLevel(violationEvent);
        return "CRITICAL".equals(alertLevel) || "EMERGENCY".equals(alertLevel);
    }

    /**
     * 获取推荐处理动作（简化版本）
     */
    private String getRecommendedAction(RuleViolationEvent violationEvent) {
        if (requiresImmediateResponse(violationEvent)) {
            return "立即停车并等待指示";
        }
        if (isCriticalViolation(violationEvent)) {
            return "立即离开限制区域";
        }
        return "调整路径避免违规";
    }

    /**
     * 从执行上下文中获取车辆类型
     */
    private String getVehicleTypeFromContext(Map<String, Object> context) {
        if (context != null && context.containsKey("vehicleType")) {
            Object vehicleTypeObj = context.get("vehicleType");
            if (vehicleTypeObj != null) {
                return vehicleTypeObj.toString();
            }
        }
        return "UNMANNED_VEHICLE"; // 项目只管理无人车
    }

    /**
     * 创建性能指标信息
     */
    private Map<String, Object> createPerformanceMetrics(RuleExecutionEvent event) {
        Map<String, Object> metrics = new HashMap<>();
        metrics.put("executionTime", event.getExecutionDurationMs());
        metrics.put("startTime", event.getExecutionStartTime());
        metrics.put("endTime", event.getExecutionEndTime());
        metrics.put("successful", event.isExecutionSuccessful());
        if (event.getErrorMessage() != null) {
            metrics.put("errorMessage", event.getErrorMessage());
        }
        return metrics;
    }

    /**
     * 确定影响范围
     */
    private String determineImpactScope(RuleStateChangeEvent event) {
        if (event.isAffectsRuntime()) {
            return "RUNTIME";
        }
        if (event.getChangeType() == RuleStateChangeEvent.StateChangeType.CONFIGURATION_UPDATE) {
            return "CONFIGURATION";
        }
        return "METADATA";
    }

    /**
     * 创建回滚信息
     */
    private Map<String, Object> createRollbackInfo(RuleStateChangeEvent event) {
        Map<String, Object> rollbackInfo = new HashMap<>();
        rollbackInfo.put("previousStatus", event.getPreviousStatus() != null ? event.getPreviousStatus().name() : "UNKNOWN");
        rollbackInfo.put("changeTime", event.getChangeTimestamp());
        rollbackInfo.put("changeType", event.getChangeType() != null ? event.getChangeType().name() : "UNKNOWN");
        return rollbackInfo;
    }

    /**
     * 确定通知级别
     */
    private String determineNotificationLevel(RuleStateChangeEvent event) {
        if (event.isAffectsRuntime()) {
            return "HIGH";
        }
        if (event.requiresNotification()) {
            return "MEDIUM";
        }
        return "LOW";
    }

    /**
     * 发布路径冲突告警WebSocket消息
     * 
     * @param message 路径冲突告警消息
     */
    public void publishPathConflictAlert(PathConflictAlertMessage message) {
        try {
            // 创建路径冲突告警WebSocket事件
            PathConflictAlertWebSocketEvent webSocketEvent = PathConflictAlertWebSocketEvent.create(message);
            eventPublisher.publishEvent(webSocketEvent);
            
            logger.info("Published path conflict alert WebSocket event: conflictId={}, alertType={}", 
                       message.getConflictId(), message.getAlertType());
                       
        } catch (Exception e) {
            logger.error("Failed to publish path conflict alert WebSocket event: conflictId={}", 
                        message.getConflictId(), e);
        }
    }

    /**
     * 通过vehicle_id动态查询车牌号
     * 
     * @param vehicleId 车辆ID
     * @return 车牌号，如果查询失败返回"UNKNOWN"
     */
    private String getLicensePlateByVehicleId(Long vehicleId) {
        if (vehicleId == null) {
            return "UNKNOWN";
        }
        
        try {
            // 通过注入的QuapDataAdapter查询车辆信息
            Optional<SysVehicleInfo> vehicleInfoOpt = quapDataAdapter.findVehicleById(vehicleId);
            if (vehicleInfoOpt.isPresent()) {
                return vehicleInfoOpt.get().getLicensePlate();
            } else {
                logger.warn("未找到vehicleId: {} 对应的车辆信息，使用默认车牌号。", vehicleId);
                return "ID-" + vehicleId; // 如果未找到，返回一个标识性的ID
            }
        } catch (Exception e) {
            logger.error("查询vehicleId: {} 对应的车牌号失败: {}", vehicleId, e.getMessage());
            return "UNKNOWN";
        }
    }
} 