//! 统一错误处理系统
//! 基于 SDK 错误类型设计，提供错误映射和恢复策略

use anyhow::{Result, anyhow};
use std::fmt;
use std::time::Duration;
use tracing::{error, warn, info, debug};
use serde::{Serialize, Deserialize};

/// 统一错误类型
#[derive(Debug, Clone, thiserror::Error)]
pub enum ComfyUIError {
    /// 连接错误
    #[error("连接错误: {message}")]
    Connection { message: String, retryable: bool },

    /// 认证错误
    #[error("认证错误: {message}")]
    Authentication { message: String },

    /// 配置错误
    #[error("配置错误: {message}")]
    Configuration { message: String, field: Option<String> },

    /// 模板错误
    #[error("模板错误: {message}")]
    Template { message: String, template_id: Option<String> },

    /// 执行错误
    #[error("执行错误: {message}")]
    Execution { message: String, prompt_id: Option<String> },

    /// 验证错误
    #[error("验证错误: {message}")]
    Validation { message: String, field: Option<String> },

    /// 数据库错误
    #[error("数据库错误: {message}")]
    Database { message: String },

    /// 文件系统错误
    #[error("文件系统错误: {message}")]
    FileSystem { message: String, path: Option<String> },

    /// 网络错误
    #[error("网络错误: {message}")]
    Network { message: String, retryable: bool },

    /// 超时错误
    #[error("超时错误: {message}")]
    Timeout { message: String, duration: Option<Duration> },

    /// 资源不足错误
    #[error("资源不足: {message}")]
    ResourceExhausted { message: String, resource_type: String },

    /// 内部错误
    #[error("内部错误: {message}")]
    Internal { message: String },

    /// SDK 错误
    #[error("SDK 错误: {0}")]
    Sdk(String),
}

impl From<comfyui_sdk::error::ComfyUIError> for ComfyUIError {
    fn from(error: comfyui_sdk::error::ComfyUIError) -> Self {
        ComfyUIError::Sdk(error.to_string())
    }
}

impl ComfyUIError {
    /// 检查错误是否可重试
    pub fn is_retryable(&self) -> bool {
        match self {
            ComfyUIError::Connection { retryable, .. } => *retryable,
            ComfyUIError::Network { retryable, .. } => *retryable,
            ComfyUIError::Timeout { .. } => true,
            ComfyUIError::ResourceExhausted { .. } => true,
            ComfyUIError::Sdk(sdk_error) => {
                // 检查 SDK 错误字符串是否包含可重试的错误类型
                sdk_error.contains("Http") ||
                sdk_error.contains("Timeout") ||
                sdk_error.contains("Connection")
            }
            _ => false,
        }
    }

    /// 获取错误严重程度
    pub fn severity(&self) -> ErrorSeverity {
        match self {
            ComfyUIError::Authentication { .. } => ErrorSeverity::Critical,
            ComfyUIError::Configuration { .. } => ErrorSeverity::High,
            ComfyUIError::Database { .. } => ErrorSeverity::High,
            ComfyUIError::Internal { .. } => ErrorSeverity::High,
            ComfyUIError::Connection { .. } => ErrorSeverity::Medium,
            ComfyUIError::Network { .. } => ErrorSeverity::Medium,
            ComfyUIError::Execution { .. } => ErrorSeverity::Medium,
            ComfyUIError::Template { .. } => ErrorSeverity::Medium,
            ComfyUIError::Timeout { .. } => ErrorSeverity::Low,
            ComfyUIError::Validation { .. } => ErrorSeverity::Low,
            ComfyUIError::FileSystem { .. } => ErrorSeverity::Low,
            ComfyUIError::ResourceExhausted { .. } => ErrorSeverity::Medium,
            ComfyUIError::Sdk(_) => ErrorSeverity::Medium,
        }
    }

    /// 获取用户友好的错误消息
    pub fn user_message(&self) -> String {
        match self {
            ComfyUIError::Connection { .. } => "无法连接到 ComfyUI 服务，请检查服务是否正常运行".to_string(),
            ComfyUIError::Authentication { .. } => "身份验证失败，请检查凭据".to_string(),
            ComfyUIError::Configuration { field, .. } => {
                if let Some(field) = field {
                    format!("配置项 '{}' 设置有误，请检查配置", field)
                } else {
                    "配置设置有误，请检查配置".to_string()
                }
            }
            ComfyUIError::Template { template_id, .. } => {
                if let Some(id) = template_id {
                    format!("模板 '{}' 处理失败", id)
                } else {
                    "模板处理失败".to_string()
                }
            }
            ComfyUIError::Execution { .. } => "工作流执行失败，请检查输入参数和工作流配置".to_string(),
            ComfyUIError::Validation { field, .. } => {
                if let Some(field) = field {
                    format!("字段 '{}' 验证失败", field)
                } else {
                    "输入验证失败".to_string()
                }
            }
            ComfyUIError::Database { .. } => "数据库操作失败，请稍后重试".to_string(),
            ComfyUIError::FileSystem { .. } => "文件操作失败，请检查文件权限".to_string(),
            ComfyUIError::Network { .. } => "网络连接失败，请检查网络设置".to_string(),
            ComfyUIError::Timeout { .. } => "操作超时，请稍后重试".to_string(),
            ComfyUIError::ResourceExhausted { resource_type, .. } => {
                format!("{} 资源不足，请稍后重试", resource_type)
            }
            ComfyUIError::Internal { .. } => "内部错误，请联系技术支持".to_string(),
            ComfyUIError::Sdk(_) => "ComfyUI SDK 错误，请检查服务状态".to_string(),
        }
    }

    /// 获取建议的恢复操作
    pub fn recovery_suggestions(&self) -> Vec<String> {
        match self {
            ComfyUIError::Connection { .. } => vec![
                "检查 ComfyUI 服务是否正在运行".to_string(),
                "验证服务器地址和端口配置".to_string(),
                "检查防火墙设置".to_string(),
            ],
            ComfyUIError::Authentication { .. } => vec![
                "检查用户名和密码".to_string(),
                "验证 API 密钥是否有效".to_string(),
            ],
            ComfyUIError::Configuration { .. } => vec![
                "检查配置文件格式".to_string(),
                "验证所有必需的配置项".to_string(),
                "重置为默认配置".to_string(),
            ],
            ComfyUIError::Template { .. } => vec![
                "检查模板格式是否正确".to_string(),
                "验证模板参数定义".to_string(),
                "尝试重新导入模板".to_string(),
            ],
            ComfyUIError::Execution { .. } => vec![
                "检查输入参数是否正确".to_string(),
                "验证工作流节点配置".to_string(),
                "查看 ComfyUI 服务日志".to_string(),
            ],
            ComfyUIError::Network { .. } => vec![
                "检查网络连接".to_string(),
                "尝试重新连接".to_string(),
                "检查代理设置".to_string(),
            ],
            ComfyUIError::Timeout { .. } => vec![
                "增加超时时间设置".to_string(),
                "检查服务器性能".to_string(),
                "稍后重试".to_string(),
            ],
            _ => vec!["稍后重试".to_string()],
        }
    }
}

/// 错误严重程度
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum ErrorSeverity {
    /// 低 - 用户可以继续操作
    Low,
    /// 中 - 影响部分功能
    Medium,
    /// 高 - 影响主要功能
    High,
    /// 严重 - 系统无法正常工作
    Critical,
}

/// 错误处理器
pub struct ErrorHandler {
    /// 错误统计
    error_stats: std::sync::Arc<tokio::sync::RwLock<ErrorStats>>,
}

impl ErrorHandler {
    /// 创建新的错误处理器
    pub fn new() -> Self {
        Self {
            error_stats: std::sync::Arc::new(tokio::sync::RwLock::new(ErrorStats::new())),
        }
    }

    /// 处理错误
    pub async fn handle_error(&self, error: &ComfyUIError, context: Option<&str>) -> ErrorHandleResult {
        // 记录错误统计
        self.record_error(error).await;

        // 记录日志
        self.log_error(error, context);

        // 生成处理结果
        ErrorHandleResult {
            error: error.clone(),
            severity: error.severity(),
            user_message: error.user_message(),
            recovery_suggestions: error.recovery_suggestions(),
            should_retry: error.is_retryable(),
            context: context.map(|s| s.to_string()),
        }
    }

    /// 记录错误统计
    async fn record_error(&self, error: &ComfyUIError) {
        let mut stats = self.error_stats.write().await;
        stats.record_error(error);
    }

    /// 记录错误日志
    fn log_error(&self, error: &ComfyUIError, context: Option<&str>) {
        let context_str = context.unwrap_or("未知上下文");
        
        match error.severity() {
            ErrorSeverity::Critical => {
                error!("严重错误 [{}]: {}", context_str, error);
            }
            ErrorSeverity::High => {
                error!("高级错误 [{}]: {}", context_str, error);
            }
            ErrorSeverity::Medium => {
                warn!("中级错误 [{}]: {}", context_str, error);
            }
            ErrorSeverity::Low => {
                info!("低级错误 [{}]: {}", context_str, error);
            }
        }
    }

    /// 获取错误统计
    pub async fn get_error_stats(&self) -> ErrorStats {
        self.error_stats.read().await.clone()
    }

    /// 清除错误统计
    pub async fn clear_error_stats(&self) {
        let mut stats = self.error_stats.write().await;
        *stats = ErrorStats::new();
    }
}

/// 错误处理结果
#[derive(Debug)]
pub struct ErrorHandleResult {
    pub error: ComfyUIError,
    pub severity: ErrorSeverity,
    pub user_message: String,
    pub recovery_suggestions: Vec<String>,
    pub should_retry: bool,
    pub context: Option<String>,
}

/// 错误统计
#[derive(Debug, Clone)]
pub struct ErrorStats {
    pub total_errors: u64,
    pub errors_by_type: std::collections::HashMap<String, u64>,
    pub errors_by_severity: std::collections::HashMap<ErrorSeverity, u64>,
    pub last_error_time: Option<chrono::DateTime<chrono::Utc>>,
}

impl ErrorStats {
    fn new() -> Self {
        Self {
            total_errors: 0,
            errors_by_type: std::collections::HashMap::new(),
            errors_by_severity: std::collections::HashMap::new(),
            last_error_time: None,
        }
    }

    fn record_error(&mut self, error: &ComfyUIError) {
        self.total_errors += 1;
        self.last_error_time = Some(chrono::Utc::now());

        // 按类型统计
        let error_type = match error {
            ComfyUIError::Connection { .. } => "Connection",
            ComfyUIError::Authentication { .. } => "Authentication",
            ComfyUIError::Configuration { .. } => "Configuration",
            ComfyUIError::Template { .. } => "Template",
            ComfyUIError::Execution { .. } => "Execution",
            ComfyUIError::Validation { .. } => "Validation",
            ComfyUIError::Database { .. } => "Database",
            ComfyUIError::FileSystem { .. } => "FileSystem",
            ComfyUIError::Network { .. } => "Network",
            ComfyUIError::Timeout { .. } => "Timeout",
            ComfyUIError::ResourceExhausted { .. } => "ResourceExhausted",
            ComfyUIError::Internal { .. } => "Internal",
            ComfyUIError::Sdk(_) => "Sdk",
        };

        *self.errors_by_type.entry(error_type.to_string()).or_insert(0) += 1;

        // 按严重程度统计
        *self.errors_by_severity.entry(error.severity()).or_insert(0) += 1;
    }
}

/// 从标准错误转换
impl From<anyhow::Error> for ComfyUIError {
    fn from(error: anyhow::Error) -> Self {
        ComfyUIError::Internal {
            message: error.to_string(),
        }
    }
}

/// 从数据库错误转换
impl From<rusqlite::Error> for ComfyUIError {
    fn from(error: rusqlite::Error) -> Self {
        ComfyUIError::Database {
            message: error.to_string(),
        }
    }
}

/// 从 IO 错误转换
impl From<std::io::Error> for ComfyUIError {
    fn from(error: std::io::Error) -> Self {
        ComfyUIError::FileSystem {
            message: error.to_string(),
            path: None,
        }
    }
}

/// 从 JSON 错误转换
impl From<serde_json::Error> for ComfyUIError {
    fn from(error: serde_json::Error) -> Self {
        ComfyUIError::Validation {
            message: format!("JSON 解析错误: {}", error),
            field: None,
        }
    }
}

/// 重试策略
#[derive(Debug, Clone)]
pub struct RetryStrategy {
    /// 最大重试次数
    pub max_attempts: u32,
    /// 初始延迟
    pub initial_delay: Duration,
    /// 最大延迟
    pub max_delay: Duration,
    /// 退避倍数
    pub backoff_multiplier: f64,
    /// 是否启用抖动
    pub jitter: bool,
}

impl Default for RetryStrategy {
    fn default() -> Self {
        Self {
            max_attempts: 3,
            initial_delay: Duration::from_millis(1000),
            max_delay: Duration::from_secs(30),
            backoff_multiplier: 2.0,
            jitter: true,
        }
    }
}

impl RetryStrategy {
    /// 计算下次重试的延迟时间
    pub fn calculate_delay(&self, attempt: u32) -> Duration {
        let base_delay = self.initial_delay.as_millis() as f64 * self.backoff_multiplier.powi(attempt as i32);
        let delay = Duration::from_millis(base_delay as u64).min(self.max_delay);

        if self.jitter {
            // 添加 ±25% 的随机抖动
            let jitter_factor = 0.75 + (rand::random::<f64>() * 0.5);
            Duration::from_millis((delay.as_millis() as f64 * jitter_factor) as u64)
        } else {
            delay
        }
    }
}

/// 重试执行器
pub struct RetryExecutor {
    strategy: RetryStrategy,
    error_handler: ErrorHandler,
}

impl RetryExecutor {
    /// 创建新的重试执行器
    pub fn new(strategy: RetryStrategy) -> Self {
        Self {
            strategy,
            error_handler: ErrorHandler::new(),
        }
    }

    /// 使用默认策略创建
    pub fn with_default_strategy() -> Self {
        Self::new(RetryStrategy::default())
    }

    /// 执行带重试的操作
    pub async fn execute<F, T, E>(&self, operation: F, context: &str) -> Result<T, ComfyUIError>
    where
        F: Fn() -> std::pin::Pin<Box<dyn std::future::Future<Output = Result<T, E>> + Send>> + Send + Sync,
        E: Into<ComfyUIError> + Send,
    {
        let mut last_error = None;

        for attempt in 0..self.strategy.max_attempts {
            match operation().await {
                Ok(result) => {
                    if attempt > 0 {
                        info!("操作在第 {} 次重试后成功: {}", attempt + 1, context);
                    }
                    return Ok(result);
                }
                Err(error) => {
                    let comfyui_error = error.into();
                    last_error = Some(comfyui_error.clone());

                    // 处理错误
                    let handle_result = self.error_handler.handle_error(&comfyui_error, Some(context)).await;

                    // 如果不可重试或已达到最大重试次数，直接返回错误
                    if !handle_result.should_retry || attempt == self.strategy.max_attempts - 1 {
                        return Err(comfyui_error);
                    }

                    // 计算延迟时间并等待
                    let delay = self.strategy.calculate_delay(attempt);
                    warn!("操作失败，第 {} 次重试，延迟 {:?}: {}", attempt + 1, delay, context);
                    tokio::time::sleep(delay).await;
                }
            }
        }

        Err(last_error.unwrap_or(ComfyUIError::Internal {
            message: "重试执行失败".to_string(),
        }))
    }

    /// 获取错误统计
    pub async fn get_error_stats(&self) -> ErrorStats {
        self.error_handler.get_error_stats().await
    }
}
