// Copyright (c) 2026 Kirky.X
//
// Licensed under the MIT License
// See LICENSE file in the project root for full license information.

//! 统一错误类型模块
//!
//! 定义 DBNexus 项目中所有错误类型的统一接口。
//!
//! # 主要类型
//!
//! - [`DbError`] - 主错误类型，统一所有数据库操作错误
//! - [`DbResult`] - 统一的结果类型别名
//! - [`PoolError`] - 连接池相关错误
//! - [`PermissionError`] - 权限相关错误
//! - [`ConfigError`] - 配置相关错误

use sea_orm::DbErr;
use thiserror::Error;

/// 数据库操作错误
///
/// 这是 DBNexus 的主要错误类型，用于包装 [`sea_orm::DbErr`] 并提供统一的错误分类。
///
/// # 错误类别
///
/// - [`DbError::Connection`] - 连接错误（网络、认证、超时等）
/// - [`DbError::Config`] - 配置错误
/// - [`DbError::Permission`] - 权限错误
/// - [`DbError::Transaction`] - 事务错误
/// - [`DbError::Migration`] - 迁移错误
///
/// # 示例
///
/// ```rust
/// use dbnexus::DbError;
///
/// // 检查错误类型
/// // match error {
/// //     DbError::Connection(_) => { /* 处理连接错误 */ }
/// //     DbError::Permission(msg) => { /* 处理权限错误 */ }
/// //     _ => { /* 其他错误 */ }
/// // }
/// ```
#[derive(Debug, Error, PartialEq)]
pub enum DbError {
    /// 连接错误
    ///
    /// 包括网络问题、认证失败、连接超时、连接被拒绝等。
    #[error("Connection error: {0}")]
    Connection(#[from] DbErr),

    /// 配置错误
    ///
    /// 配置相关错误，如验证失败、格式错误等。
    #[error("Configuration error: {0}")]
    Config(String),

    /// 权限错误
    ///
    /// 权限检查失败，如无权限访问、操作被拒绝等。
    #[error("Permission denied: {0}")]
    Permission(String),

    /// 事务错误
    ///
    /// 事务相关错误，如回滚失败、并发冲突等。
    #[error("Transaction error: {0}")]
    Transaction(String),

    /// 迁移错误
    ///
    /// 数据库迁移相关错误。
    #[error("Migration error: {0}")]
    Migration(String),
}

impl DbError {
    /// 判断是否为连接错误
    ///
    /// 连接错误包括网络问题、认证失败、连接超时等。
    ///
    /// # Returns
    ///
    /// 如果是连接相关错误返回 `true`
    pub fn is_connection_error(&self) -> bool {
        matches!(self, DbError::Connection(_))
    }

    /// 判断是否为查询错误
    ///
    /// 查询错误包括 SQL 语法错误、约束违反、找不到记录等。
    ///
    /// # Returns
    ///
    /// 如果是查询相关错误返回 `true`
    pub fn is_query_error(&self) -> bool {
        match self {
            DbError::Connection(err) => {
                let err_msg = err.to_string().to_lowercase();
                // 连接错误不算查询错误
                !err_msg.contains("connection") && !err_msg.contains("timeout") && !err_msg.contains("refused")
            }
            // Config, Permission, Transaction, Migration 变体可能是查询错误
            _ => true,
        }
    }

    /// 判断是否为事务错误
    ///
    /// # Returns
    ///
    /// 如果是事务相关错误返回 `true`
    pub fn is_transaction_error(&self) -> bool {
        matches!(self, DbError::Transaction(_))
    }
}

impl From<PoolError> for DbError {
    fn from(err: PoolError) -> Self {
        DbError::Config(err.to_string())
    }
}

impl From<PermissionError> for DbError {
    fn from(err: PermissionError) -> Self {
        DbError::Permission(err.to_string())
    }
}

impl From<ConfigError> for DbError {
    fn from(err: ConfigError) -> Self {
        DbError::Config(err.to_string())
    }
}

impl From<MigrationError> for DbError {
    fn from(err: MigrationError) -> Self {
        DbError::Migration(err.to_string())
    }
}

/// 连接池错误
#[derive(Debug, thiserror::Error)]
pub enum PoolError {
    /// 连接获取超时
    #[error("Failed to acquire connection within timeout")]
    AcquireTimeout,

    /// 连接池已耗尽
    #[error("Connection pool exhausted")]
    PoolExhausted,

    /// 连接创建失败
    #[error("Failed to create connection: {0}")]
    ConnectionFailed(String),

    /// 健康检查失败
    #[error("Health check failed: {0}")]
    HealthCheckFailed(String),
}

/// 权限错误
#[derive(Debug, thiserror::Error)]
pub enum PermissionError {
    /// 权限被拒绝
    #[error("Permission denied for {operation} on {resource}")]
    Denied {
        /// 目标资源
        resource: String,
        /// 操作类型
        operation: String,
    },

    /// 角色未找到
    #[error("Role not found: {0}")]
    RoleNotFound(String),

    /// 无效的权限配置
    #[error("Invalid permission configuration: {0}")]
    InvalidConfig(String),

    /// 速率限制
    #[error("Rate limit exceeded")]
    RateLimited,
}

/// 配置错误
#[derive(Debug, thiserror::Error)]
pub enum ConfigError {
    /// 缺少必需字段
    #[error("Missing required field: {0}")]
    MissingField(&'static str),

    /// 格式错误
    #[error("Invalid format for field: {0}")]
    InvalidFormat(String),

    /// 文件未找到
    #[error("Configuration file not found")]
    FileNotFound,

    /// 文件读取错误
    #[error("Failed to read configuration file: {0}")]
    FileReadError(String),

    /// URL 格式错误
    #[error("Invalid database URL format: {0}")]
    InvalidUrl(String),

    /// 不支持的数据库协议
    #[error("Unsupported database protocol")]
    UnsupportedProtocol,

    /// IO 错误
    #[error("Configuration file I/O error")]
    IoError,

    /// 环境变量错误
    #[error("Environment variable error")]
    EnvVarError,

    /// 验证失败
    #[error("Configuration validation failed")]
    ValidationFailed,

    /// 内部错误
    #[cfg(feature = "dev")]
    #[error(transparent)]
    Internal(#[from] Box<dyn std::error::Error + Send + Sync>),
}

impl From<std::io::Error> for ConfigError {
    fn from(_: std::io::Error) -> Self {
        ConfigError::IoError
    }
}

impl From<std::env::VarError> for ConfigError {
    fn from(_: std::env::VarError) -> Self {
        ConfigError::EnvVarError
    }
}

/// 迁移错误
#[derive(Debug, thiserror::Error)]
pub enum MigrationError {
    /// 迁移文件未找到
    #[error("Migration file not found: {0}")]
    FileNotFound(String),

    /// 迁移文件解析错误
    #[error("Failed to parse migration file: {0}")]
    ParseError(String),

    /// 迁移执行失败
    #[error("Migration execution failed: {0}")]
    ExecutionError(String),

    /// 迁移版本冲突
    #[error("Migration version conflict: {0}")]
    VersionConflict(String),

    /// 迁移回滚失败
    #[error("Migration rollback failed: {0}")]
    RollbackError(String),
}

/// 审计错误
#[derive(Debug, thiserror::Error)]
pub enum AuditError {
    /// 审计日志写入失败
    #[error("Failed to write audit log: {0}")]
    WriteError(String),

    /// 审计日志序列化失败
    #[error("Failed to serialize audit data: {0}")]
    SerializationError(String),

    /// 审计配置错误
    #[error("Invalid audit configuration: {0}")]
    ConfigError(String),
}

/// 结果类型别名
pub type DbResult<T> = Result<T, DbError>;
/// 连接池操作结果
pub type PoolResult<T> = Result<T, PoolError>;
/// 权限检查结果
pub type PermissionResult<T> = Result<T, PermissionError>;
/// 配置操作结果
pub type ConfigResult<T> = Result<T, ConfigError>;
/// 迁移操作结果
pub type MigrationResult<T> = Result<T, MigrationError>;
/// 审计操作结果
pub type AuditResult<T> = Result<T, AuditError>;

// ============================================================================
// From 实现（用于错误类型转换）
// ============================================================================

impl From<PoolError> for DbErr {
    fn from(err: PoolError) -> Self {
        DbErr::Custom(err.to_string())
    }
}

impl From<PermissionError> for DbErr {
    fn from(err: PermissionError) -> Self {
        DbErr::Custom(err.to_string())
    }
}

impl From<ConfigError> for DbErr {
    fn from(err: ConfigError) -> Self {
        DbErr::Custom(err.to_string())
    }
}

impl From<MigrationError> for DbErr {
    fn from(err: MigrationError) -> Self {
        DbErr::Custom(err.to_string())
    }
}

impl From<AuditError> for DbErr {
    fn from(err: AuditError) -> Self {
        DbErr::Custom(err.to_string())
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    /// TEST-E-001: DbError is_connection_error 测试
    #[test]
    fn test_db_error_is_connection_error() {
        // Connection 变体
        let conn_err = DbError::Connection(sea_orm::DbErr::ConnectionAcquire(sea_orm::ConnAcquireErr::Timeout));
        assert!(conn_err.is_connection_error());

        // 其他变体不算连接错误
        let config_err = DbError::Config("test".to_string());
        assert!(!config_err.is_connection_error());

        let perm_err = DbError::Permission("denied".to_string());
        assert!(!perm_err.is_connection_error());

        let txn_err = DbError::Transaction("rollback".to_string());
        assert!(!txn_err.is_connection_error());
    }

    /// TEST-E-002: DbError is_transaction_error 测试
    #[test]
    fn test_db_error_is_transaction_error() {
        // Transaction 变体
        let txn_err = DbError::Transaction("deadlock".to_string());
        assert!(txn_err.is_transaction_error());

        // 其他变体不算事务错误
        let conn_err = DbError::Connection(sea_orm::DbErr::ConnectionAcquire(sea_orm::ConnAcquireErr::Timeout));
        assert!(!conn_err.is_transaction_error());

        let config_err = DbError::Config("test".to_string());
        assert!(!config_err.is_transaction_error());
    }

    /// TEST-E-003: DbError is_query_error 测试
    #[test]
    fn test_db_error_is_query_error() {
        // Connection 变体中的查询错误
        let conn_err = DbError::Connection(sea_orm::DbErr::Query(sea_orm::RuntimeErr::Internal(
            "syntax error".to_string(),
        )));
        assert!(conn_err.is_query_error());

        // Connection 变体中的连接错误不算查询错误
        let conn_err2 = DbError::Connection(sea_orm::DbErr::ConnectionAcquire(sea_orm::ConnAcquireErr::Timeout));
        assert!(!conn_err2.is_query_error());

        // 其他变体都算查询错误
        let config_err = DbError::Config("test".to_string());
        assert!(config_err.is_query_error());

        let perm_err = DbError::Permission("denied".to_string());
        assert!(perm_err.is_query_error());
    }

    /// TEST-E-004: From<PoolError> for DbError 测试
    #[test]
    fn test_from_pool_error() {
        let pool_err = PoolError::PoolExhausted;
        let db_err: DbError = pool_err.into();
        match db_err {
            DbError::Config(msg) => {
                assert!(msg.contains("pool") || msg.contains("exhausted"));
            }
            _ => panic!("Expected DbError::Config"),
        }
    }

    /// TEST-E-005: From<PermissionError> for DbError 测试
    #[test]
    fn test_from_permission_error() {
        let perm_err = PermissionError::Denied {
            resource: "users".to_string(),
            operation: "select".to_string(),
        };
        let db_err: DbError = perm_err.into();
        match db_err {
            DbError::Permission(msg) => {
                assert!(msg.contains("users") || msg.contains("select"));
            }
            _ => panic!("Expected DbError::Permission"),
        }
    }

    /// TEST-E-006: From<ConfigError> for DbError 测试
    #[test]
    fn test_from_config_error() {
        let config_err = ConfigError::MissingField("url");
        let db_err: DbError = config_err.into();
        match db_err {
            DbError::Config(msg) => {
                assert!(msg.contains("url") || msg.contains("missing"));
            }
            _ => panic!("Expected DbError::Config"),
        }
    }

    /// TEST-E-007: From<MigrationError> for DbError 测试
    #[test]
    fn test_from_migration_error() {
        let mig_err = MigrationError::ExecutionError("failed".to_string());
        let db_err: DbError = mig_err.into();
        match db_err {
            DbError::Migration(msg) => {
                assert!(msg.contains("failed"));
            }
            _ => panic!("Expected DbError::Migration"),
        }
    }

    /// TEST-E-008: DbResult 类型别名测试
    #[test]
    fn test_db_result_alias() {
        // 验证 DbResult 是正确的类型别名
        let success: DbResult<i32> = Ok(42);
        assert_eq!(success, Ok(42));

        let failure: DbResult<i32> = Err(DbError::Config("error".to_string()));
        assert!(failure.is_err());
    }
}
