//! Error types for the SentryAgent.ai AgentIdP Rust SDK.
//!
//! All fallible operations return `Result<T, AgentIdPError>`. Match on the
//! variants to handle specific conditions such as rate-limiting or
//! missing resources.

/// The unified error type returned by all SDK operations.
///
/// # Examples
///
/// ```rust,no_run
/// use sentryagent_idp::AgentIdPError;
///
/// async fn example(client: &sentryagent_idp::AgentIdPClient) {
///     match client.get_agent("unknown-id").await {
///         Err(AgentIdPError::NotFound(id)) => eprintln!("Agent not found: {}", id),
///         Err(AgentIdPError::RateLimited { retry_after_secs }) => {
///             eprintln!("Rate limited — retry after {}s", retry_after_secs);
///         }
///         Err(e) => eprintln!("Unexpected error: {}", e),
///         Ok(agent) => println!("Found: {:?}", agent),
///     }
/// }
/// ```
#[derive(Debug, thiserror::Error)]
pub enum AgentIdPError {
    /// An underlying HTTP transport error from `reqwest`.
    #[error("HTTP request failed: {0}")]
    HttpError(#[from] reqwest::Error),

    /// The API returned a non-2xx status code with a structured error body.
    #[error("API error {status}: {message}")]
    ApiError {
        /// HTTP status code returned by the API.
        status: u16,
        /// Human-readable error message from the API.
        message: String,
        /// Machine-readable error code from the API, if present.
        code: Option<String>,
    },

    /// Authentication or authorisation failed (401/403).
    #[error("Authentication failed: {0}")]
    AuthError(String),

    /// The requested resource was not found (404).
    #[error("Agent not found: {0}")]
    NotFound(String),

    /// The API rate-limited this client (429). Contains the retry delay.
    #[error("Rate limit exceeded. Retry after {retry_after_secs}s")]
    RateLimited {
        /// Seconds to wait before retrying.
        retry_after_secs: u64,
    },

    /// A required configuration value was missing or invalid.
    #[error("Invalid configuration: {0}")]
    ConfigError(String),

    /// JSON serialization or deserialization failed.
    #[error("Serialization error: {0}")]
    SerdeError(#[from] serde_json::Error),

    /// A delegation chain was invalid or could not be verified.
    #[error("Delegation chain invalid: {0}")]
    DelegationError(String),
}
