use thiserror::Error;

/// TOTP challenge data returned when step-up authentication is required.
#[derive(Debug, Clone)]
pub struct TotpChallenge {
    /// Short-lived JWT (5 min) that must be presented alongside the TOTP code.
    pub pending_token: String,
    /// When this challenge expires.
    pub expires_at: chrono::DateTime<chrono::Utc>,
}

#[derive(Debug, Error)]
#[non_exhaustive]
pub enum AuthError {
    #[error("invalid or expired token")]
    InvalidToken,

    #[error("token has expired")]
    TokenExpired,

    #[error("insufficient permissions: required role `{0}`")]
    Forbidden(String),

    #[error("invalid credentials")]
    InvalidCredentials,

    #[error("password hashing failed: {0}")]
    HashError(String),

    #[error("internal auth error: {0}")]
    Internal(String),

    /// TOTP verification is required.  The caller should prompt for a TOTP code
    /// and call [`crate::jwt::Auth::attempt_with_totp`].
    #[error("TOTP verification required")]
    TotpRequired(TotpChallenge),
}
