use erp_core::error::AppError;

/// Auth module error types
#[derive(Debug, thiserror::Error)]
pub enum AuthError {
    #[error("用户名或密码错误")]
    InvalidCredentials,

    #[error("Token 已过期")]
    TokenExpired,

    #[error("Token 已被吊销")]
    TokenRevoked,

    #[error("用户已被{0}")]
    UserDisabled(String),

    #[error("密码哈希错误")]
    HashError(String),

    #[error("JWT 错误: {0}")]
    JwtError(#[from] jsonwebtoken::errors::Error),

    #[error("数据库错误: {0}")]
    DbError(String),

    #[error("{0}")]
    Validation(String),

    #[error("{0}")]
    Forbidden(String),

    #[error("版本冲突: 数据已被其他操作修改，请刷新后重试")]
    VersionMismatch,
}

impl From<AuthError> for AppError {
    fn from(err: AuthError) -> Self {
        match err {
            AuthError::InvalidCredentials => AppError::Unauthorized,
            AuthError::TokenExpired => AppError::Unauthorized,
            AuthError::TokenRevoked => AppError::Unauthorized,
            AuthError::UserDisabled(s) => AppError::Forbidden(s),
            AuthError::Validation(s) => AppError::Validation(s),
            AuthError::Forbidden(s) => AppError::Forbidden(s),
            AuthError::DbError(_) => AppError::Internal(err.to_string()),
            AuthError::HashError(_) => AppError::Internal(err.to_string()),
            AuthError::JwtError(_) => AppError::Unauthorized,
            AuthError::VersionMismatch => AppError::VersionMismatch,
        }
    }
}

pub type AuthResult<T> = Result<T, AuthError>;

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

    #[test]
    fn auth_error_invalid_credentials_maps_to_unauthorized() {
        let app: AppError = AuthError::InvalidCredentials.into();
        match app {
            AppError::Unauthorized => {}
            other => panic!("Expected Unauthorized, got {:?}", other),
        }
    }

    #[test]
    fn auth_error_token_expired_maps_to_unauthorized() {
        let app: AppError = AuthError::TokenExpired.into();
        match app {
            AppError::Unauthorized => {}
            other => panic!("Expected Unauthorized, got {:?}", other),
        }
    }

    #[test]
    fn auth_error_user_disabled_maps_to_forbidden() {
        let app: AppError = AuthError::UserDisabled("已禁用".to_string()).into();
        match app {
            AppError::Forbidden(msg) => assert_eq!(msg, "已禁用"),
            other => panic!("Expected Forbidden, got {:?}", other),
        }
    }

    #[test]
    fn auth_error_hash_error_maps_to_internal() {
        let app: AppError = AuthError::HashError("argon2 failed".to_string()).into();
        match app {
            AppError::Internal(_) => {}
            other => panic!("Expected Internal, got {:?}", other),
        }
    }

    #[test]
    fn auth_error_validation_maps_to_validation() {
        let app: AppError = AuthError::Validation("用户名已存在".to_string()).into();
        match app {
            AppError::Validation(msg) => assert_eq!(msg, "用户名已存在"),
            other => panic!("Expected Validation, got {:?}", other),
        }
    }
}
