//! Tauri 事件发射器
//! 将实时事件发送到前端的服务

use anyhow::Result;
use std::sync::Arc;
use tauri::{AppHandle, Emitter};
use tokio::sync::broadcast;
use tracing::{info, error, debug};
use serde::{Serialize, Deserialize};

use crate::business::services::realtime_monitor_v2::{RealtimeEventV2, EventSubscriber};

/// Tauri 事件名称常量
pub mod events {
    pub const COMFYUI_CONNECTION_CHANGED: &str = "comfyui://connection-changed";
    pub const COMFYUI_EXECUTION_STARTED: &str = "comfyui://execution-started";
    pub const COMFYUI_EXECUTION_PROGRESS: &str = "comfyui://execution-progress";
    pub const COMFYUI_NODE_EXECUTING: &str = "comfyui://node-executing";
    pub const COMFYUI_EXECUTION_COMPLETED: &str = "comfyui://execution-completed";
    pub const COMFYUI_EXECUTION_FAILED: &str = "comfyui://execution-failed";
    pub const COMFYUI_QUEUE_UPDATED: &str = "comfyui://queue-updated";
    pub const COMFYUI_SYSTEM_STATUS_UPDATED: &str = "comfyui://system-status-updated";
}

/// 前端事件数据结构
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct FrontendEvent {
    pub event_type: String,
    pub data: serde_json::Value,
    pub timestamp: String,
}

/// Tauri 事件发射器
pub struct TauriEventEmitter {
    app_handle: AppHandle,
    event_receiver: Option<broadcast::Receiver<RealtimeEventV2>>,
    is_running: Arc<tokio::sync::RwLock<bool>>,
    task_handle: Arc<tokio::sync::RwLock<Option<tokio::task::JoinHandle<()>>>>,
}

impl TauriEventEmitter {
    /// 创建新的事件发射器
    pub fn new(app_handle: AppHandle) -> Self {
        Self {
            app_handle,
            event_receiver: None,
            is_running: Arc::new(tokio::sync::RwLock::new(false)),
            task_handle: Arc::new(tokio::sync::RwLock::new(None)),
        }
    }

    /// 启动事件发射器
    pub async fn start(&mut self, mut event_receiver: broadcast::Receiver<RealtimeEventV2>) -> Result<()> {
        info!("启动 Tauri 事件发射器");

        // 检查是否已经在运行
        {
            let running = self.is_running.read().await;
            if *running {
                return Ok(());
            }
        }

        let app_handle = self.app_handle.clone();
        let is_running = Arc::clone(&self.is_running);

        // 启动事件处理任务
        let handle = tokio::spawn(async move {
            {
                let mut running = is_running.write().await;
                *running = true;
            }

            info!("Tauri 事件发射器已启动");

            while let Ok(event) = event_receiver.recv().await {
                if let Err(e) = Self::emit_to_frontend(&app_handle, &event).await {
                    error!("发送事件到前端失败: {}", e);
                }
            }

            {
                let mut running = is_running.write().await;
                *running = false;
            }

            info!("Tauri 事件发射器已停止");
        });

        {
            let mut task_handle = self.task_handle.write().await;
            *task_handle = Some(handle);
        }

        Ok(())
    }

    /// 停止事件发射器
    pub async fn stop(&self) -> Result<()> {
        info!("停止 Tauri 事件发射器");

        let handle = {
            let mut task_handle = self.task_handle.write().await;
            task_handle.take()
        };

        if let Some(handle) = handle {
            handle.abort();
        }

        {
            let mut running = self.is_running.write().await;
            *running = false;
        }

        Ok(())
    }

    /// 检查是否正在运行
    pub async fn is_running(&self) -> bool {
        *self.is_running.read().await
    }

    /// 发送事件到前端
    async fn emit_to_frontend(app_handle: &AppHandle, event: &RealtimeEventV2) -> Result<()> {
        let (event_name, event_data) = Self::convert_event_for_frontend(event);

        let frontend_event = FrontendEvent {
            event_type: event_name.clone(),
            data: event_data,
            timestamp: chrono::Utc::now().to_rfc3339(),
        };

        // 发送到前端
        app_handle.emit(&event_name, &frontend_event)
            .map_err(|e| anyhow::anyhow!("发送事件失败: {}", e))?;

        debug!("已发送事件到前端: {}", event_name);
        Ok(())
    }

    /// 转换事件为前端格式
    fn convert_event_for_frontend(event: &RealtimeEventV2) -> (String, serde_json::Value) {
        match event {
            RealtimeEventV2::ConnectionChanged { connected, message, timestamp } => (
                events::COMFYUI_CONNECTION_CHANGED.to_string(),
                serde_json::json!({
                    "connected": connected,
                    "message": message,
                    "timestamp": timestamp
                })
            ),
            RealtimeEventV2::ExecutionStarted { prompt_id, execution_id, node_id, timestamp } => (
                events::COMFYUI_EXECUTION_STARTED.to_string(),
                serde_json::json!({
                    "prompt_id": prompt_id,
                    "execution_id": execution_id,
                    "node_id": node_id,
                    "timestamp": timestamp
                })
            ),
            RealtimeEventV2::ExecutionProgress { prompt_id, execution_id, node_id, progress, max_progress, percentage, timestamp } => (
                events::COMFYUI_EXECUTION_PROGRESS.to_string(),
                serde_json::json!({
                    "prompt_id": prompt_id,
                    "execution_id": execution_id,
                    "node_id": node_id,
                    "progress": progress,
                    "max_progress": max_progress,
                    "percentage": percentage,
                    "timestamp": timestamp
                })
            ),
            RealtimeEventV2::NodeExecuting { prompt_id, execution_id, node_id, node_title, timestamp } => (
                events::COMFYUI_NODE_EXECUTING.to_string(),
                serde_json::json!({
                    "prompt_id": prompt_id,
                    "execution_id": execution_id,
                    "node_id": node_id,
                    "node_title": node_title,
                    "timestamp": timestamp
                })
            ),
            RealtimeEventV2::ExecutionCompleted { prompt_id, execution_id, outputs, output_urls, execution_time, timestamp } => (
                events::COMFYUI_EXECUTION_COMPLETED.to_string(),
                serde_json::json!({
                    "prompt_id": prompt_id,
                    "execution_id": execution_id,
                    "outputs": outputs,
                    "output_urls": output_urls,
                    "execution_time": execution_time,
                    "timestamp": timestamp
                })
            ),
            RealtimeEventV2::ExecutionFailed { prompt_id, execution_id, node_id, error, details, timestamp } => (
                events::COMFYUI_EXECUTION_FAILED.to_string(),
                serde_json::json!({
                    "prompt_id": prompt_id,
                    "execution_id": execution_id,
                    "node_id": node_id,
                    "error": error,
                    "details": details,
                    "timestamp": timestamp
                })
            ),
            RealtimeEventV2::QueueUpdated { running_count, pending_count, timestamp } => (
                events::COMFYUI_QUEUE_UPDATED.to_string(),
                serde_json::json!({
                    "running_count": running_count,
                    "pending_count": pending_count,
                    "timestamp": timestamp
                })
            ),
            RealtimeEventV2::SystemStatusUpdated { memory_usage, gpu_usage, active_connections, timestamp } => (
                events::COMFYUI_SYSTEM_STATUS_UPDATED.to_string(),
                serde_json::json!({
                    "memory_usage": memory_usage,
                    "gpu_usage": gpu_usage,
                    "active_connections": active_connections,
                    "timestamp": timestamp
                })
            ),
        }
    }
}

impl EventSubscriber for TauriEventEmitter {
    fn handle_event(&self, event: &RealtimeEventV2) {
        let app_handle = self.app_handle.clone();
        let event = event.clone();
        
        // 异步发送事件
        tokio::spawn(async move {
            if let Err(e) = Self::emit_to_frontend(&app_handle, &event).await {
                error!("发送事件到前端失败: {}", e);
            }
        });
    }
}

/// 事件发射器管理器
pub struct EventEmitterManager {
    emitters: Vec<Arc<TauriEventEmitter>>,
}

impl EventEmitterManager {
    /// 创建新的管理器
    pub fn new() -> Self {
        Self {
            emitters: Vec::new(),
        }
    }

    /// 添加发射器
    pub fn add_emitter(&mut self, emitter: Arc<TauriEventEmitter>) {
        self.emitters.push(emitter);
    }

    /// 启动所有发射器
    pub async fn start_all(&mut self, event_receiver: broadcast::Receiver<RealtimeEventV2>) -> Result<()> {
        for emitter in &mut self.emitters {
            // 为每个发射器创建独立的接收器
            let receiver = event_receiver.resubscribe();
            // 注意：这里需要获取可变引用，但 Arc 不允许
            // 实际实现中可能需要重新设计架构
        }
        Ok(())
    }

    /// 停止所有发射器
    pub async fn stop_all(&self) -> Result<()> {
        for emitter in &self.emitters {
            emitter.stop().await?;
        }
        Ok(())
    }
}
