//! Error types for the Highflame SDK.

use thiserror::Error;

/// All errors that can be returned by [`Highflame`](crate::Highflame).
#[derive(Debug, Error)]
pub enum HighflameError {
    /// The API returned an RFC 9457 Problem Details response.
    #[error("[{status}] {title}: {detail}")]
    Api {
        /// HTTP status code.
        status: u16,
        /// Short title from the Problem Details body.
        title: String,
        /// Human-readable explanation.
        detail: String,
    },

    /// 401 Unauthorized — invalid or expired credentials.
    #[error("authentication error: {0}")]
    Authentication(String),

    /// 429 Too Many Requests — rate limit exceeded.
    #[error("rate limit exceeded: {0}")]
    RateLimit(String),

    /// A network or transport error (connection refused, timeout, TLS, …).
    #[error("connection error: {0}")]
    ApiConnection(String),

    /// The response body could not be deserialised.
    #[error("deserialisation error: {0}")]
    Deserialisation(#[from] serde_json::Error),
}

impl HighflameError {
    /// Returns the HTTP status code if this is an API-level error.
    pub fn status(&self) -> Option<u16> {
        match self {
            HighflameError::Api { status, .. } => Some(*status),
            HighflameError::Authentication(_) => Some(401),
            HighflameError::RateLimit(_) => Some(429),
            _ => None,
        }
    }

    /// Returns `true` if this is an API-level error (HTTP 4xx / 5xx).
    pub fn is_api_error(&self) -> bool {
        matches!(self, HighflameError::Api { .. })
    }

    /// Returns `true` if this is a 401 authentication error.
    pub fn is_authentication_error(&self) -> bool {
        matches!(self, HighflameError::Authentication(_))
    }

    /// Returns `true` if this is a 429 rate-limit error.
    pub fn is_rate_limit_error(&self) -> bool {
        matches!(self, HighflameError::RateLimit(_))
    }

    /// Returns `true` if this is a connection / transport error.
    pub fn is_connection_error(&self) -> bool {
        matches!(self, HighflameError::ApiConnection(_))
    }
}

impl From<reqwest::Error> for HighflameError {
    fn from(e: reqwest::Error) -> Self {
        HighflameError::ApiConnection(e.to_string())
    }
}
