//! WebSocket 消息处理器

use crate::database::Database;
use crate::models::{ChatMessage, MessageStatus, MessageType};

use super::ConnectionManager;

/// 最大重试次数
const MAX_SAVE_RETRIES: u32 = 3;

/// 消息处理器
pub struct MessageHandler;

impl MessageHandler {
    /// 保存消息到数据库（带重试）
    fn save_message_with_retry(message: &ChatMessage) -> bool {
        for attempt in 1..=MAX_SAVE_RETRIES {
            match Database::save_message(message) {
                Ok(_) => {
                    log::debug!("Message {} saved successfully", message.id);
                    return true;
                }
                Err(e) => {
                    log::error!(
                        "Failed to save message {} (attempt {}/{}): {}",
                        message.id, attempt, MAX_SAVE_RETRIES, e
                    );
                    if attempt < MAX_SAVE_RETRIES {
                        // 短暂延迟后重试
                        std::thread::sleep(std::time::Duration::from_millis(50));
                    }
                }
            }
        }
        false
    }

    /// 处理收到的消息
    pub async fn handle_message(
        message: ChatMessage,
        connection_manager: &ConnectionManager,
        local_device_id: &str,
    ) {
        match message.message_type {
            MessageType::Text | MessageType::Image | MessageType::File => {
                // 保存消息到数据库（带重试机制）
                let saved = Self::save_message_with_retry(&message);
                if !saved {
                    log::error!("Message {} could not be saved after {} retries", message.id, MAX_SAVE_RETRIES);
                }
                
                // 发送确认回执（只有保存成功才发送）
                if saved {
                    let ack = ChatMessage::new_ack(
                        local_device_id.to_string(),
                        message.from.clone(),
                        &message.id,
                    );
                    
                    if let Err(e) = connection_manager.send_to(&message.from, &ack).await {
                        log::error!("Failed to send ack: {}", e);
                    }
                }
                
                // 无论是否保存成功，都触发消息接收事件（让用户能看到消息）
                connection_manager.emit_message_received(message);
            }
            MessageType::Event => {
                // 处理事件消息 (如在线/离线通知)
                // 这是内部握手消息，不发送到前端显示
                log::info!("Received event: {} from {}", message.content, message.from);
                // 可以在这里处理特定事件，如更新设备在线状态等
            }
            MessageType::Ack => {
                // 处理确认回执，更新消息状态
                let message_id = &message.content;
                if let Err(e) = Database::update_message_status(message_id, MessageStatus::Delivered) {
                    log::error!("Failed to update message status: {}", e);
                }
            }
            MessageType::Ping => {
                // 收到 ping，回复 pong
                let pong = ChatMessage::new_pong(
                    local_device_id.to_string(),
                    message.from.clone(),
                );
                
                if let Err(e) = connection_manager.send_to(&message.from, &pong).await {
                    log::error!("Failed to send pong: {}", e);
                }
            }
            MessageType::Pong => {
                // 收到 pong，更新心跳时间
                log::debug!("Received pong from {}", message.from);
            }
        }
    }
}

/// 心跳管理器
pub struct HeartbeatManager;

impl HeartbeatManager {
    /// 启动心跳任务
    pub fn start(
        connection_manager: ConnectionManager,
        local_device_id: String,
        interval_ms: u64,
    ) {
        tokio::spawn(async move {
            let interval = std::time::Duration::from_millis(interval_ms);
            
            loop {
                tokio::time::sleep(interval).await;
                
                let devices = connection_manager.connected_devices();
                for device_id in devices {
                    let ping = ChatMessage::new_ping(local_device_id.clone());
                    if let Err(e) = connection_manager.send_to(&device_id, &ping).await {
                        log::warn!("Failed to send heartbeat to {}: {}", device_id, e);
                    }
                }
            }
        });
    }
}
