/// 事件总线系统
/// 遵循 Tauri 开发规范的事件驱动架构设计
use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use tokio::sync::broadcast;
use serde::{Serialize, Deserialize};
use crate::data::models::material::MaterialImportResult;

/// 事件类型定义
/// 遵循模块化设计原则，清晰分类不同类型的事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum Event {
    /// 用户操作事件
    UserAction(UserActionEvent),
    /// 系统事件
    System(SystemEvent),
    /// 数据事件
    Data(DataEvent),
    /// UI事件
    UI(UIEvent),
    /// 性能事件
    Performance(PerformanceEvent),
}

/// 用户操作事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum UserActionEvent {
    ProjectCreated { project_id: String, project_name: String },
    ProjectDeleted { project_id: String },
    ProjectUpdated { project_id: String },
    FileSelected { file_path: String },
}

/// 系统事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum SystemEvent {
    ApplicationStarted,
    ApplicationShutdown,
    DatabaseInitialized,
    PluginLoaded { plugin_name: String },
    PluginUnloaded { plugin_name: String },
}

/// 数据事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum DataEvent {
    ProjectDataChanged { project_id: String },
    DatabaseError { error_message: String },
    DataSyncCompleted,
    /// 素材导入进度事件
    MaterialImportProgress {
        project_id: String,
        current_file: String,
        processed_count: u32,
        total_count: u32,
        current_status: String,
        progress_percentage: f64,
    },
    /// 素材导入完成事件
    MaterialImportCompleted {
        project_id: String,
        result: MaterialImportResult,
    },
    /// 素材导入失败事件
    MaterialImportFailed {
        project_id: String,
        error: String,
    },
    /// 单个素材处理进度事件
    MaterialProcessingProgress {
        material_id: String,
        file_name: String,
        stage: String, // "metadata", "scene_detection", "video_splitting"
        progress_percentage: f64,
    },
    /// 批量匹配进度事件
    BatchMatchingProgress {
        project_id: String,
        current_binding_index: u32,
        total_bindings: u32,
        current_template_name: Option<String>,
        completed_bindings: u32,
        failed_bindings: u32,
        elapsed_time_ms: u64,
    },
}

/// UI事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum UIEvent {
    WindowResized { width: u32, height: u32 },
    ThemeChanged { theme: String },
    LanguageChanged { language: String },
    StateChanged,
}

/// 性能事件
#[derive(Debug, Clone, Serialize, Deserialize)]
pub enum PerformanceEvent {
    PerformanceWarning { metric: String, value: f64 },
    PerformanceThresholdExceeded { metric: String, threshold: f64, actual: f64 },
}

/// 事件处理器类型
pub type EventHandler = Box<dyn Fn(&Event) + Send + Sync>;

/// 事件总线
/// 遵循 Tauri 开发规范的组件通信设计
pub struct EventBus {
    handlers: Arc<Mutex<HashMap<String, Vec<EventHandler>>>>,
    sender: broadcast::Sender<Event>,
}

impl EventBus {
    /// 创建新的事件总线
    /// 遵循安全第一原则，使用适当的缓冲区大小
    pub fn new() -> Self {
        let (sender, _) = broadcast::channel(1000);

        Self {
            handlers: Arc::new(Mutex::new(HashMap::new())),
            sender,
        }
    }

    /// 订阅事件
    /// 遵循类型安全原则，确保事件处理的安全性
    pub fn subscribe<F>(&self, event_type: &str, handler: F)
    where
        F: Fn(&Event) + Send + Sync + 'static,
    {
        let mut handlers = self.handlers.lock().unwrap();
        handlers
            .entry(event_type.to_string())
            .or_insert_with(Vec::new)
            .push(Box::new(handler));
    }

    /// 发布事件
    /// 遵循异步编程最佳实践
    pub async fn publish(&self, event: Event) -> Result<(), String> {
        // 发送到广播通道
        self.sender.send(event.clone()).map_err(|e| e.to_string())?;

        // 调用注册的处理器
        if let Ok(handlers) = self.handlers.lock() {
            let event_type = self.get_event_type(&event);
            if let Some(event_handlers) = handlers.get(&event_type) {
                for handler in event_handlers {
                    handler(&event);
                }
            }
        }

        Ok(())
    }

    /// 获取事件接收器
    pub fn get_receiver(&self) -> broadcast::Receiver<Event> {
        self.sender.subscribe()
    }

    /// 获取事件类型字符串
    fn get_event_type(&self, event: &Event) -> String {
        match event {
            Event::UserAction(_) => "user_action".to_string(),
            Event::System(_) => "system".to_string(),
            Event::Data(_) => "data".to_string(),
            Event::UI(_) => "ui".to_string(),
            Event::Performance(_) => "performance".to_string(),
        }
    }

    /// 取消订阅（简化实现）
    pub fn unsubscribe(&self, event_type: &str) {
        if let Ok(mut handlers) = self.handlers.lock() {
            handlers.remove(event_type);
        }
    }

    /// 获取订阅者数量
    pub fn get_subscriber_count(&self, event_type: &str) -> usize {
        if let Ok(handlers) = self.handlers.lock() {
            handlers.get(event_type).map(|h| h.len()).unwrap_or(0)
        } else {
            0
        }
    }
}

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

/// 事件总线管理器
/// 提供全局事件总线访问
pub struct EventBusManager {
    event_bus: Arc<EventBus>,
}

impl EventBusManager {
    /// 创建新的事件总线管理器
    pub fn new() -> Self {
        Self {
            event_bus: Arc::new(EventBus::new()),
        }
    }

    /// 获取事件总线实例
    pub fn get_event_bus(&self) -> Arc<EventBus> {
        Arc::clone(&self.event_bus)
    }

    /// 发布系统启动事件
    pub async fn publish_app_started(&self) -> Result<(), String> {
        self.event_bus.publish(Event::System(SystemEvent::ApplicationStarted)).await
    }

    /// 发布系统关闭事件
    pub async fn publish_app_shutdown(&self) -> Result<(), String> {
        self.event_bus.publish(Event::System(SystemEvent::ApplicationShutdown)).await
    }

    /// 发布项目创建事件
    pub async fn publish_project_created(&self, project_id: String, project_name: String) -> Result<(), String> {
        self.event_bus.publish(Event::UserAction(UserActionEvent::ProjectCreated {
            project_id,
            project_name,
        })).await
    }

    /// 发布性能警告事件
    pub async fn publish_performance_warning(&self, metric: String, value: f64) -> Result<(), String> {
        self.event_bus.publish(Event::Performance(PerformanceEvent::PerformanceWarning {
            metric,
            value,
        })).await
    }

    /// 发布素材导入进度事件
    pub async fn publish_material_import_progress(
        &self,
        project_id: String,
        current_file: String,
        processed_count: u32,
        total_count: u32,
        current_status: String,
    ) -> Result<(), String> {
        let progress_percentage = if total_count > 0 {
            (processed_count as f64 / total_count as f64) * 100.0
        } else {
            0.0
        };

        self.event_bus.publish(Event::Data(DataEvent::MaterialImportProgress {
            project_id,
            current_file,
            processed_count,
            total_count,
            current_status,
            progress_percentage,
        })).await
    }

    /// 发布素材导入完成事件
    pub async fn publish_material_import_completed(
        &self,
        project_id: String,
        result: MaterialImportResult,
    ) -> Result<(), String> {
        self.event_bus.publish(Event::Data(DataEvent::MaterialImportCompleted {
            project_id,
            result,
        })).await
    }

    /// 发布素材导入失败事件
    pub async fn publish_material_import_failed(
        &self,
        project_id: String,
        error: String,
    ) -> Result<(), String> {
        self.event_bus.publish(Event::Data(DataEvent::MaterialImportFailed {
            project_id,
            error,
        })).await
    }

    /// 发布素材处理进度事件
    pub async fn publish_material_processing_progress(
        &self,
        material_id: String,
        file_name: String,
        stage: String,
        progress_percentage: f64,
    ) -> Result<(), String> {
        self.event_bus.publish(Event::Data(DataEvent::MaterialProcessingProgress {
            material_id,
            file_name,
            stage,
            progress_percentage,
        })).await
    }

    /// 发布批量匹配进度事件
    pub async fn publish_batch_matching_progress(
        &self,
        project_id: String,
        current_binding_index: u32,
        total_bindings: u32,
        current_template_name: Option<String>,
        completed_bindings: u32,
        failed_bindings: u32,
        elapsed_time_ms: u64,
    ) -> Result<(), String> {
        self.event_bus.publish(Event::Data(DataEvent::BatchMatchingProgress {
            project_id,
            current_binding_index,
            total_bindings,
            current_template_name,
            completed_bindings,
            failed_bindings,
            elapsed_time_ms,
        })).await
    }
}

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

#[cfg(test)]
mod tests {
    use super::*;
    use std::sync::atomic::{AtomicUsize, Ordering};
    use tokio::time::{sleep, Duration};

    #[tokio::test]
    async fn test_event_bus_publish_subscribe() {
        let event_bus = EventBus::new();
        let counter = Arc::new(AtomicUsize::new(0));
        let counter_clone = Arc::clone(&counter);

        // 订阅事件
        event_bus.subscribe("system", move |_event| {
            counter_clone.fetch_add(1, Ordering::SeqCst);
        });

        // 发布事件
        let event = Event::System(SystemEvent::ApplicationStarted);
        event_bus.publish(event).await.unwrap();

        // 等待事件处理
        sleep(Duration::from_millis(10)).await;

        // 验证事件被处理
        assert_eq!(counter.load(Ordering::SeqCst), 1);
    }

    #[tokio::test]
    async fn test_event_bus_manager() {
        let manager = EventBusManager::new();
        
        // 测试发布系统事件
        assert!(manager.publish_app_started().await.is_ok());
        assert!(manager.publish_project_created("test-id".to_string(), "Test Project".to_string()).await.is_ok());
    }
}
