use anyhow::{Result, anyhow};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use std::collections::HashMap;
use std::time::Duration;
use tracing::{info, warn, error, debug};
use tokio::time::sleep;

use crate::config::ComfyUISettings;
use crate::data::models::outfit_photo_generation::{
    WorkflowProgress, WorkflowNodeReplacement
};

// 导入 ComfyUI SDK 类型
use comfyui_sdk::types::{
    ComfyUIClientConfig, ExecutionOptions, TemplateExecutionResult,
    QueueStatus as SDKQueueStatus, SystemStats, ObjectInfo
};
use comfyui_sdk::client::ComfyUIClient;
use comfyui_sdk::templates::{WorkflowTemplate, TemplateManager};

/// ComfyUI SDK 服务包装器
/// 使用 comfyui-sdk crate 提供更好的 ComfyUI 集成
pub struct ComfyUISDKService {
    client: ComfyUIClient,
    settings: ComfyUISettings,
}

/// 工作流执行结果
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WorkflowExecutionResult {
    pub prompt_id: String,
    pub outputs: HashMap<String, Vec<String>>,
    pub execution_time: Duration,
    pub node_outputs: HashMap<String, Value>,
}

/// 工作流执行配置
#[derive(Debug)]
pub struct SDKExecutionConfig {
    pub timeout: Duration,
    pub retry_attempts: u32,
}

impl Default for SDKExecutionConfig {
    fn default() -> Self {
        Self {
            timeout: Duration::from_secs(300), // 5分钟默认超时
            retry_attempts: 3,
        }
    }
}

impl ComfyUISDKService {
    /// 创建新的 ComfyUI SDK 服务实例
    pub fn new(settings: ComfyUISettings) -> Result<Self> {
        let config = ComfyUIClientConfig {
            base_url: settings.base_url(),
            timeout: Some(Duration::from_secs(settings.timeout_seconds)),
            retry_attempts: Some(settings.sdk_config.sdk_retry_attempts),
            retry_delay: Some(Duration::from_millis(1000)),
            headers: None,
        };

        let client = ComfyUIClient::new(config)?;

        Ok(Self {
            client,
            settings,
        })
    }

    /// 检查 ComfyUI 服务状态
    pub async fn check_health(&self) -> Result<bool> {
        match self.client.get_system_stats().await {
            Ok(_) => {
                info!("ComfyUI 服务健康检查通过");
                Ok(true)
            }
            Err(e) => {
                warn!("ComfyUI 服务健康检查失败: {}", e);
                Ok(false)
            }
        }
    }

    /// 获取队列状态
    pub async fn get_queue_status(&self) -> Result<QueueStatus> {
        let queue_info = self.client.get_queue_status().await?;

        Ok(QueueStatus {
            running: queue_info.queue_running.len(),
            pending: queue_info.queue_pending.len(),
        })
    }

    /// 执行工作流（直接使用 JSON 工作流）
    pub async fn execute_workflow(
        &self,
        workflow: Value,
        config: SDKExecutionConfig,
    ) -> Result<WorkflowExecutionResult> {
        let start_time = std::time::Instant::now();

        // 由于 SDK 使用模板系统，我们需要创建一个临时模板
        // 或者直接使用 HTTP 客户端提交工作流
        let result = self.execute_raw_workflow(workflow, config).await?;

        let execution_time = start_time.elapsed();
        info!("工作流执行完成，耗时: {:?}", execution_time);

        let outputs = result.outputs.unwrap_or_default();
        Ok(WorkflowExecutionResult {
            prompt_id: result.prompt_id,
            outputs: self.extract_image_urls(&outputs),
            execution_time,
            node_outputs: outputs,
        })
    }

    /// 执行原始工作流（绕过模板系统）
    async fn execute_raw_workflow(
        &self,
        workflow: Value,
        config: SDKExecutionConfig,
    ) -> Result<TemplateExecutionResult> {
        // 使用 HTTP 客户端直接提交工作流
        let prompt_request = comfyui_sdk::types::PromptRequest {
            prompt: if let Value::Object(map) = workflow {
                map.into_iter().collect()
            } else {
                return Err(anyhow!("工作流必须是 JSON 对象"));
            },
            client_id: None,
            extra_data: None,
        };

        let prompt_response = self.client.http().queue_prompt(&prompt_request).await?;
        let prompt_id = prompt_response.prompt_id.clone();

        info!("工作流已提交，prompt_id: {}", prompt_id);

        // 等待执行完成
        let execution_options = ExecutionOptions {
            timeout: Some(config.timeout),
            priority: None,
        };

        // 使用 SDK 的等待机制
        self.wait_for_completion_with_sdk(&prompt_id, execution_options).await
    }

    /// 使用 SDK 等待工作流完成
    async fn wait_for_completion_with_sdk(
        &self,
        prompt_id: &str,
        options: ExecutionOptions,
    ) -> Result<TemplateExecutionResult> {
        let start_time = std::time::Instant::now();
        let timeout_duration = options.timeout.unwrap_or(Duration::from_secs(300));
        let check_interval = Duration::from_millis(1000);

        loop {
            // 检查超时
            if start_time.elapsed() > timeout_duration {
                let execution_time = start_time.elapsed().as_millis() as u64;
                let error = comfyui_sdk::types::ExecutionError {
                    node_id: None,
                    message: format!("执行超时，超过 {:?}", timeout_duration),
                    details: None,
                    timestamp: chrono::Utc::now(),
                };
                return Ok(TemplateExecutionResult::failure(prompt_id.to_string(), error, execution_time));
            }

            // 检查历史记录
            match self.client.http().get_history_by_prompt(prompt_id).await {
                Ok(history) => {
                    if let Some(history_item) = history.get(prompt_id) {
                        if history_item.status.completed {
                            let execution_time = start_time.elapsed().as_millis() as u64;
                            let mut outputs = HashMap::new();

                            // 转换输出格式
                            for (node_id, node_outputs) in &history_item.outputs {
                                let mut node_output = HashMap::new();
                                for (output_name, output_list) in node_outputs {
                                    node_output.insert(output_name.clone(), serde_json::to_value(output_list)?);
                                }
                                outputs.insert(node_id.clone(), serde_json::to_value(node_output)?);
                            }

                            return Ok(TemplateExecutionResult::success(prompt_id.to_string(), outputs, execution_time));
                        }
                    }
                }
                Err(e) => {
                    warn!("检查历史记录失败: {}", e);
                }
            }

            sleep(check_interval).await;
        }
    }

    /// 从输出中提取图片 URL
    fn extract_image_urls(&self, outputs: &HashMap<String, serde_json::Value>) -> HashMap<String, Vec<String>> {
        let mut image_urls = HashMap::new();

        for (node_id, node_output) in outputs {
            if let Some(images) = self.extract_images_from_node_output(node_output) {
                if !images.is_empty() {
                    image_urls.insert(node_id.clone(), images);
                }
            }
        }

        image_urls
    }

    /// 从节点输出中提取图片
    fn extract_images_from_node_output(&self, node_output: &serde_json::Value) -> Option<Vec<String>> {
        // 尝试不同的输出格式
        if let Some(images) = node_output.get("images") {
            if let Some(images_array) = images.as_array() {
                let urls: Vec<String> = images_array
                    .iter()
                    .filter_map(|img| {
                        img.get("filename")
                            .and_then(|f| f.as_str())
                            .map(|filename| {
                                format!("{}/view?filename={}", self.settings.base_url(), filename)
                            })
                    })
                    .collect();

                if !urls.is_empty() {
                    return Some(urls);
                }
            }
        }

        None
    }







    /// 取消工作流执行
    pub async fn cancel_workflow(&self, prompt_id: &str) -> Result<()> {
        self.client.interrupt().await?;
        info!("已取消工作流执行: {}", prompt_id);
        Ok(())
    }

    /// 获取可用模型列表
    pub async fn get_available_models(&self) -> Result<Vec<String>> {
        let object_info = self.client.get_object_info().await?;
        let models = Vec::new();
        
        // 从 object_info 中提取模型信息
        // 这里需要根据实际的 API 响应结构来实现
        
        Ok(models)
    }
}

/// 队列状态
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct QueueStatus {
    pub running: usize,
    pub pending: usize,
}


