use thiserror::Error;

/// 应用程序错误类型
#[derive(Error, Debug)]
pub enum AppError {
    /// 数据库相关错误
    #[error("数据库错误: {message}")]
    Database { message: String },

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

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

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

    /// 权限错误
    #[error("权限不足: {operation}")]
    Permission { operation: String },

    /// 验证错误
    #[error("验证失败: {field} - {message}")]
    Validation { field: String, message: String },

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

/// 素材处理相关错误
#[derive(Error, Debug)]
pub enum MaterialError {
    /// 文件不存在
    #[error("文件不存在: {path}")]
    FileNotFound { path: String },

    /// 文件格式不支持
    #[error("不支持的文件格式: {format} (文件: {path})")]
    UnsupportedFormat { format: String, path: String },

    /// FFmpeg 执行错误
    #[error("FFmpeg 执行失败: {command} - {message}")]
    FFmpegError { command: String, message: String },

    /// 场景检测错误
    #[error("场景检测失败: {reason} (文件: {path})")]
    SceneDetectionError { reason: String, path: String },

    /// 视频切分错误
    #[error("视频切分失败: {reason} (文件: {path})")]
    VideoSegmentationError { reason: String, path: String },

    /// 元数据提取错误
    #[error("元数据提取失败: {reason} (文件: {path})")]
    MetadataExtractionError { reason: String, path: String },

    /// 导入错误
    #[error("素材导入失败: {reason}")]
    ImportError { reason: String },

    /// 处理超时
    #[error("处理超时: {operation} (超时时间: {timeout_seconds}秒)")]
    ProcessingTimeout { operation: String, timeout_seconds: u64 },

    /// 存储空间不足
    #[error("存储空间不足: 需要 {required_mb}MB，可用 {available_mb}MB")]
    InsufficientStorage { required_mb: u64, available_mb: u64 },
}

/// 项目管理相关错误
#[derive(Error, Debug)]
pub enum ProjectError {
    /// 项目不存在
    #[error("项目不存在: {id}")]
    ProjectNotFound { id: String },

    /// 项目路径无效
    #[error("项目路径无效: {path} - {reason}")]
    InvalidPath { path: String, reason: String },

    /// 项目已存在
    #[error("项目已存在: {name} (路径: {path})")]
    ProjectExists { name: String, path: String },

    /// 项目创建失败
    #[error("项目创建失败: {reason}")]
    CreationFailed { reason: String },

    /// 项目删除失败
    #[error("项目删除失败: {reason}")]
    DeletionFailed { reason: String },

    /// 项目更新失败
    #[error("项目更新失败: {reason}")]
    UpdateFailed { reason: String },
}

/// 数据库相关错误
#[derive(Error, Debug)]
pub enum DatabaseError {
    /// 连接失败
    #[error("数据库连接失败: {message}")]
    ConnectionFailed { message: String },

    /// 查询失败
    #[error("数据库查询失败: {query} - {message}")]
    QueryFailed { query: String, message: String },

    /// 事务失败
    #[error("数据库事务失败: {message}")]
    TransactionFailed { message: String },

    /// 迁移失败
    #[error("数据库迁移失败: {version} - {message}")]
    MigrationFailed { version: String, message: String },

    /// 数据完整性错误
    #[error("数据完整性错误: {constraint} - {message}")]
    IntegrityError { constraint: String, message: String },
}

/// 系统相关错误
#[derive(Error, Debug)]
pub enum SystemError {
    /// 平台不支持
    #[error("平台不支持: {platform} - {feature}")]
    UnsupportedPlatform { platform: String, feature: String },

    /// 系统资源不足
    #[error("系统资源不足: {resource} - {message}")]
    InsufficientResources { resource: String, message: String },

    /// 外部依赖缺失
    #[error("外部依赖缺失: {dependency} - {message}")]
    MissingDependency { dependency: String, message: String },

    /// 系统调用失败
    #[error("系统调用失败: {call} - {message}")]
    SystemCallFailed { call: String, message: String },
}

/// 业务逻辑相关错误
#[derive(Error, Debug)]
pub enum BusinessError {
    /// 输入验证错误
    #[error("输入验证失败: {0}")]
    InvalidInput(String),

    /// 重复名称错误
    #[error("名称已存在: {0}")]
    DuplicateName(String),

    /// 资源不存在
    #[error("资源不存在: {0}")]
    NotFound(String),

    /// 业务规则违反
    #[error("业务规则违反: {0}")]
    BusinessRuleViolation(String),

    /// 操作不被允许
    #[error("操作不被允许: {0}")]
    OperationNotAllowed(String),

    /// 状态无效
    #[error("状态无效: {0}")]
    InvalidState(String),
}

/// 错误结果类型别名
pub type AppResult<T> = Result<T, AppError>;
pub type MaterialResult<T> = Result<T, MaterialError>;
pub type ProjectResult<T> = Result<T, ProjectError>;
pub type DatabaseResult<T> = Result<T, DatabaseError>;
pub type SystemResult<T> = Result<T, SystemError>;
pub type BusinessResult<T> = Result<T, BusinessError>;

/// 错误转换实现
impl From<rusqlite::Error> for DatabaseError {
    fn from(err: rusqlite::Error) -> Self {
        DatabaseError::QueryFailed {
            query: "unknown".to_string(),
            message: err.to_string(),
        }
    }
}

impl From<std::io::Error> for AppError {
    fn from(err: std::io::Error) -> Self {
        AppError::FileSystem {
            message: err.to_string(),
        }
    }
}

impl From<serde_json::Error> for AppError {
    fn from(err: serde_json::Error) -> Self {
        AppError::Configuration {
            message: format!("JSON 解析错误: {}", err),
        }
    }
}

impl From<MaterialError> for AppError {
    fn from(err: MaterialError) -> Self {
        AppError::Internal {
            message: err.to_string(),
        }
    }
}

impl From<ProjectError> for AppError {
    fn from(err: ProjectError) -> Self {
        AppError::Internal {
            message: err.to_string(),
        }
    }
}

impl From<DatabaseError> for AppError {
    fn from(err: DatabaseError) -> Self {
        AppError::Database {
            message: err.to_string(),
        }
    }
}

impl From<SystemError> for AppError {
    fn from(err: SystemError) -> Self {
        AppError::Internal {
            message: err.to_string(),
        }
    }
}

impl From<BusinessError> for AppError {
    fn from(err: BusinessError) -> Self {
        match err {
            BusinessError::InvalidInput(msg) => AppError::Validation {
                field: "input".to_string(),
                message: msg,
            },
            BusinessError::DuplicateName(name) => AppError::Validation {
                field: "name".to_string(),
                message: format!("名称 '{}' 已存在", name),
            },
            BusinessError::NotFound(resource) => AppError::Internal {
                message: format!("资源不存在: {}", resource),
            },
            BusinessError::BusinessRuleViolation(rule) => AppError::Internal {
                message: format!("业务规则违反: {}", rule),
            },
            BusinessError::OperationNotAllowed(operation) => AppError::Permission {
                operation,
            },
            BusinessError::InvalidState(state) => AppError::Internal {
                message: format!("状态无效: {}", state),
            },
        }
    }
}

/// 错误处理工具函数
pub mod error_utils {
    use super::*;
    use tracing::{error, warn};

    /// 记录并转换错误
    pub fn log_and_convert<E: std::error::Error>(err: E, context: &str) -> AppError {
        error!("错误发生在 {}: {}", context, err);
        AppError::Internal {
            message: format!("{}: {}", context, err),
        }
    }

    /// 记录警告并返回默认值
    pub fn log_warning_and_default<T: Default>(err: impl std::error::Error, context: &str) -> T {
        warn!("警告在 {}: {}", context, err);
        T::default()
    }

    /// 验证文件路径
    pub fn validate_file_path(path: &str) -> MaterialResult<()> {
        if path.is_empty() {
            return Err(MaterialError::FileNotFound {
                path: path.to_string(),
            });
        }

        let path_obj = std::path::Path::new(path);
        if !path_obj.exists() {
            return Err(MaterialError::FileNotFound {
                path: path.to_string(),
            });
        }

        if !path_obj.is_file() {
            return Err(MaterialError::FileNotFound {
                path: path.to_string(),
            });
        }

        Ok(())
    }

    /// 验证目录路径
    pub fn validate_directory_path(path: &str) -> ProjectResult<()> {
        if path.is_empty() {
            return Err(ProjectError::InvalidPath {
                path: path.to_string(),
                reason: "路径为空".to_string(),
            });
        }

        let path_obj = std::path::Path::new(path);
        if !path_obj.exists() {
            return Err(ProjectError::InvalidPath {
                path: path.to_string(),
                reason: "路径不存在".to_string(),
            });
        }

        if !path_obj.is_dir() {
            return Err(ProjectError::InvalidPath {
                path: path.to_string(),
                reason: "不是有效的目录".to_string(),
            });
        }

        Ok(())
    }

    /// 检查存储空间
    pub fn check_storage_space(required_mb: u64) -> MaterialResult<()> {
        // 简化实现，实际应用中应该检查真实的磁盘空间
        let available_mb = 1000; // 模拟可用空间
        
        if available_mb < required_mb {
            return Err(MaterialError::InsufficientStorage {
                required_mb,
                available_mb,
            });
        }

        Ok(())
    }
}
