//! 设备管理器
//! 管理已发现的设备列表，处理设备超时

use dashmap::DashMap;
use std::sync::Arc;
use std::time::Duration;
use tokio::sync::broadcast;

use crate::models::DeviceInfo;
use crate::utils::DEVICE_TIMEOUT_MS;

use super::DiscoveryEvent;

/// 设备管理器
#[derive(Clone)]
pub struct DeviceManager {
    /// 已发现的设备 (device_id -> DeviceInfo)
    devices: Arc<DashMap<String, DeviceInfo>>,
    /// 事件发送器
    event_tx: broadcast::Sender<DiscoveryEvent>,
}

impl DeviceManager {
    /// 创建新的设备管理器
    pub fn new() -> Self {
        let (event_tx, _) = broadcast::channel(100);
        Self {
            devices: Arc::new(DashMap::new()),
            event_tx,
        }
    }

    /// 获取事件订阅
    pub fn subscribe(&self) -> broadcast::Receiver<DiscoveryEvent> {
        self.event_tx.subscribe()
    }

    /// 添加或更新设备
    pub fn upsert_device(&self, mut device: DeviceInfo) {
        device.touch();
        let device_id = device.device_id.clone();
        let is_new = !self.devices.contains_key(&device_id);
        
        self.devices.insert(device_id, device.clone());
        
        if is_new {
            let _ = self.event_tx.send(DiscoveryEvent::DeviceFound(device));
        }
    }

    /// 移除设备
    pub fn remove_device(&self, device_id: &str) {
        if self.devices.remove(device_id).is_some() {
            let _ = self.event_tx.send(DiscoveryEvent::DeviceLost(device_id.to_string()));
        }
    }

    /// 获取设备信息
    pub fn get_device(&self, device_id: &str) -> Option<DeviceInfo> {
        self.devices.get(device_id).map(|d| d.clone())
    }

    /// 获取所有在线设备
    pub fn get_all_devices(&self) -> Vec<DeviceInfo> {
        self.devices.iter().map(|d| d.clone()).collect()
    }

    /// 获取在线设备数量
    pub fn device_count(&self) -> usize {
        self.devices.len()
    }

    /// 启动超时检查任务
    pub fn start_timeout_checker(&self) {
        let devices = self.devices.clone();
        let event_tx = self.event_tx.clone();
        let timeout = Duration::from_millis(DEVICE_TIMEOUT_MS);

        tokio::spawn(async move {
            let check_interval = Duration::from_secs(5);
            
            loop {
                tokio::time::sleep(check_interval).await;
                
                let now = chrono::Utc::now().timestamp();
                let timeout_secs = timeout.as_secs() as i64;
                
                let mut expired_ids = Vec::new();
                
                for entry in devices.iter() {
                    if now - entry.last_seen > timeout_secs {
                        expired_ids.push(entry.device_id.clone());
                    }
                }
                
                for device_id in expired_ids {
                    if devices.remove(&device_id).is_some() {
                        log::info!("Device {} timed out", device_id);
                        let _ = event_tx.send(DiscoveryEvent::DeviceLost(device_id));
                    }
                }
            }
        });
    }

    /// 设置设备在线状态
    pub fn set_device_online(&self, device_id: &str, online: bool) {
        if let Some(mut device) = self.devices.get_mut(device_id) {
            device.online = online;
            if online {
                device.touch();
            }
        }
    }

    /// 检查设备是否在线
    pub fn is_device_online(&self, device_id: &str) -> bool {
        self.devices.contains_key(device_id)
    }

    /// 清空所有设备
    pub fn clear(&self) {
        let device_ids: Vec<String> = self.devices.iter().map(|d| d.device_id.clone()).collect();
        self.devices.clear();
        
        for device_id in device_ids {
            let _ = self.event_tx.send(DiscoveryEvent::DeviceLost(device_id));
        }
    }
}

impl Default for DeviceManager {
    fn default() -> Self {
        Self::new()
    }
}
