package com.qaup.collision.websocket.broadcaster;

import com.qaup.collision.websocket.cache.MessageCacheService;
import com.qaup.collision.websocket.event.CollisionWarningEvent;
import com.qaup.collision.websocket.event.PositionUpdateEvent;
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.GeofenceAlertWebSocketEvent;
import com.qaup.collision.websocket.event.PathConflictAlertWebSocketEvent;
import com.qaup.collision.websocket.event.TrafficLightStatusEvent;
import com.qaup.collision.websocket.event.VehicleCommandEvent;
import com.qaup.collision.websocket.message.CollisionWarningPayload;
import com.qaup.collision.websocket.message.MessageTypeConstants;
import com.qaup.collision.websocket.message.GeofenceAlertPayload;
import com.qaup.collision.websocket.message.PositionUpdatePayload;
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.TrafficLightStatusPayload;
import com.qaup.collision.websocket.message.VehicleCommandPayload;
import com.qaup.collision.websocket.message.UniversalMessage;
import com.qaup.collision.websocket.message.PathConflictAlertMessage;
import com.qaup.collision.websocket.handler.CollisionWebSocketHandler;

import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.event.EventListener;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.util.List;
import java.util.UUID;

/**
 * WebSocket统一消息广播器
 * 监听所有WebSocket事件，使用原生WebSocket统一推送到控制台前端
 */
@Component
public class WebSocketMessageBroadcaster {
    
    private final MessageCacheService messageCacheService;
    private final CollisionWebSocketHandler collisionWebSocketHandler; // 注入实例
    private final ObjectMapper objectMapper; // JSON序列化器

    @Autowired
    public WebSocketMessageBroadcaster(MessageCacheService messageCacheService, CollisionWebSocketHandler collisionWebSocketHandler, ObjectMapper objectMapper) {
        this.messageCacheService = messageCacheService;
        this.collisionWebSocketHandler = collisionWebSocketHandler;
        this.objectMapper = objectMapper;
    }
    
    /**
     * 处理位置更新事件
     * @param event 位置更新事件
     */
    @EventListener
    public void handlePositionUpdate(PositionUpdateEvent event) {
        UniversalMessage<PositionUpdatePayload> message = UniversalMessage.<PositionUpdatePayload>builder()
                .type(MessageTypeConstants.POSITION_UPDATE)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((PositionUpdatePayload) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    /**
     * 处理车辆指令事件
     * @param event 车辆指令事件
     */
    @EventListener
    public void handleVehicleCommand(VehicleCommandEvent event) {
        UniversalMessage<VehicleCommandPayload> message = UniversalMessage.<VehicleCommandPayload>builder()
                .type(MessageTypeConstants.VEHICLE_COMMAND)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((VehicleCommandPayload) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    /**
     * 处理红绿灯状态事件
     * @param event 红绿灯状态事件
     */
    @EventListener
    public void handleTrafficLightStatus(TrafficLightStatusEvent event) {
        UniversalMessage<TrafficLightStatusPayload> message = UniversalMessage.<TrafficLightStatusPayload>builder()
                .type(MessageTypeConstants.TRAFFIC_LIGHT_STATUS)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((TrafficLightStatusPayload) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    /**
     * 处理碰撞预警事件
     * @param event 碰撞预警事件
     */
    @EventListener
    public void handleCollisionWarning(CollisionWarningEvent event) {
        UniversalMessage<CollisionWarningPayload> message = UniversalMessage.<CollisionWarningPayload>builder()
                .type(MessageTypeConstants.COLLISION_WARNING)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((CollisionWarningPayload) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    // === 规则事件处理方法 ===
    
    /**
     * 处理规则违规事件
     * @param event 规则违规事件
     */
    @EventListener
    public void handleRuleViolation(RuleViolationWebSocketEvent event) {
        UniversalMessage<RuleViolationPayload> message = UniversalMessage.<RuleViolationPayload>builder()
                .type(MessageTypeConstants.RULE_VIOLATION)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((RuleViolationPayload) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    /**
     * 处理规则执行状态事件
     * @param event 规则执行状态事件
     */
    @EventListener
    public void handleRuleExecutionStatus(RuleExecutionStatusWebSocketEvent event) {
        UniversalMessage<RuleExecutionStatusPayload> message = UniversalMessage.<RuleExecutionStatusPayload>builder()
                .type(MessageTypeConstants.RULE_EXECUTION_STATUS)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((RuleExecutionStatusPayload) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    /**
     * 处理规则状态变更事件
     * @param event 规则状态变更事件
     */
    @EventListener
    public void handleRuleStateChange(RuleStateChangeWebSocketEvent event) {
        UniversalMessage<RuleStateChangePayload> message = UniversalMessage.<RuleStateChangePayload>builder()
                .type(MessageTypeConstants.RULE_STATE_CHANGE)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((RuleStateChangePayload) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    /**
     * 处理路径冲突告警事件
     * @param event 路径冲突告警事件
     */
    @EventListener
    public void handlePathConflictAlert(PathConflictAlertWebSocketEvent event) {
        UniversalMessage<PathConflictAlertMessage> message = UniversalMessage.<PathConflictAlertMessage>builder()
                .type(MessageTypeConstants.PATH_CONFLICT_ALERT)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((PathConflictAlertMessage) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    /**
     * 处理电子围栏告警事件
     * @param event 电子围栏告警事件
     */
    @EventListener
    public void handleGeofenceAlert(GeofenceAlertWebSocketEvent event) {
        UniversalMessage<GeofenceAlertPayload> message = UniversalMessage.<GeofenceAlertPayload>builder()
                .type(MessageTypeConstants.GEOFENCE_ALERT)
                .timestamp(event.getTimestamp())
                .messageId(generateMessageId())
                .payload((GeofenceAlertPayload) event.getPayload())
                .build();
        
        broadcastMessage(message);
    }
    
    /**
     * 统一消息广播方法 - 使用原生WebSocket发送JSON消息
     * @param message 要广播的消息
     */
    private void broadcastMessage(UniversalMessage<?> message) {
        try {
            // 使用Jackson ObjectMapper将UniversalMessage序列化为JSON字符串
            // 这样前端可以获得消息类型、时间戳、消息ID等完整信息
            String jsonMessage = objectMapper.writeValueAsString(message);
            this.collisionWebSocketHandler.broadcastMessage(jsonMessage);    
            
            // 缓存消息用于重连恢复
            messageCacheService.cacheMessage(message);
            
        } catch (Exception e) {
            System.err.println("Failed to broadcast message via native WebSocket: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    /**
     * 生成唯一消息ID
     * @return 消息ID
     */
    private String generateMessageId() {
        return UUID.randomUUID().toString();
    }
    
    /**
     * 获取最近消息（用于客户端重连恢复）
     * @param messageType 消息类型，为空则获取所有类型
     * @param count 消息数量
     * @return 最近消息列表
     */
    public void sendRecentMessages(String messageType, int count) {
        try {
            List<UniversalMessage<?>> recentMessages = messageType == null || messageType.trim().isEmpty() 
                    ? messageCacheService.getAllRecentMessages(count)
                    : messageCacheService.getRecentMessages(messageType, count);
            
            // 逐个发送最近消息
            recentMessages.forEach(this::broadcastMessage);
            
        } catch (Exception e) {
            System.err.println("Failed to send recent messages: " + e.getMessage());
        }
    }
    
    /**
     * 获取当前WebSocket连接数
     * @return 连接数量
     */
    public int getOnlineCount() {
        return this.collisionWebSocketHandler.getConnectionCount();
    }
} 