use std::fmt::{Display, Formatter};

/// Encapsulate common exception types
///
/// 实现Error trait以兼容标准错误处理
#[derive(Debug)]
pub enum Exception {

    // 输入/输出相关错误
    Io(std::io::Error),          // 包装标准IO错误
    FileNotFound(String),        // 文件未找到（带文件名）
    DirectoryCreationFailed(String), // 目录创建失败

    // 解析相关错误
    ParseError(String),          // 解析失败（带错误信息）
    InvalidFormat,               // 格式无效
    MissingField(String),        // 缺少必填字段（带字段名）

    // 网络相关错误
    ConnectionFailed(String),    // 连接失败（带地址）
    Timeout,                     // 超时
    InvalidUrl(String),          // 无效URL
    ReqwestErr(reqwest::Error),

    // 数据相关错误
    DataNotFound,                // 数据未找到
    DuplicateEntry(String),      // 重复条目（带标识）
    InvalidData(String),         // 无效数据（带描述）

    // 权限相关错误
    PermissionDenied,            // 权限不足
    Unauthorized,                // 未授权

    // 配置相关错误
    ConfigError(String),         // 配置错误
    MissingConfig(String),       // 缺少配置项

    // 其他通用错误
    Unknown(String),             // 未知错误（带信息）
    NotImplemented,              // 功能未实现

}

impl Display for Exception {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        match self {
            Exception::Io(e) => write!(f, "IO错误: {}", e),
            Exception::FileNotFound(name) => write!(f, "文件未找到: {}", name),
            Exception::ParseError(msg) => write!(f, "解析错误: {}", msg),
            Exception::Unknown(msg) => write!(f, "未知错误: {}", msg),
            _ => write!(f, "{:?}", self), // 对未特别处理的错误使用Debug输出
        }
    }
}

// 实现Error trait以兼容标准错误处理
impl std::error::Error for Exception { }

impl From<chrono::ParseError> for Exception {
    fn from(err: chrono::ParseError) -> Self {
        Exception::ParseError(format!("时间解析错误: {}", err))
    }
}

impl From<std::io::Error> for Exception {
    fn from(err: std::io::Error) -> Self {
        Exception::Io(err)
    }
}

impl From<serde_yaml::Error> for Exception {
    fn from(err: serde_yaml::Error) -> Self {
        Exception::ParseError(format!("YAML解析错误: {}", err))
    }
}

impl From<reqwest::Error> for Exception {
    fn from(err: reqwest::Error) -> Self {
        Exception::ReqwestErr(err)
    }
}

#[cfg(feature = "db-sqlite")]
impl From<sqlite::Error> for Exception {
    fn from(value: sqlite::Error) -> Self {
        Exception::Unknown(value.to_string())
    }
}

#[cfg(feature = "db-mysql")]
impl From<mysql::Error> for Exception {
    fn from(value: mysql::Error) -> Self {
        match value {
            _ => Exception::Unknown(value.to_string()),
        }
    }
}

#[cfg(feature = "db-mysql")]
impl From<mysql::UrlError> for Exception {
    fn from(value: mysql::UrlError) -> Self {
        match value {
            _ => Exception::Unknown(value.to_string()),
        }
    }
}

impl From<url::ParseError> for Exception {
    fn from(value: url::ParseError) -> Self {
        Exception::InvalidUrl(value.to_string())
    }
    
}

impl From<notify::Error> for Exception {
    fn from(value: notify::Error) -> Self {
        Exception::Unknown(value.to_string())
    }
}