use thiserror::Error;

#[derive(Error, Debug)]
pub enum LlmError {
    #[allow(dead_code)] // Matched in error mapping but not constructed; kept for API completeness
    #[error("API key not configured for provider: {0}")]
    MissingApiKey(String),

    #[error("Authentication failed: invalid API key")]
    AuthenticationFailed,

    #[error("Rate limited: retry after {retry_after_secs} seconds")]
    RateLimited { retry_after_secs: u64 },

    #[error("Service unavailable: {0}")]
    ServiceUnavailable(String),

    #[error("Request timeout after {0} seconds")]
    Timeout(u64),

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

    #[error("Invalid response format: {0}")]
    InvalidResponse(String),

    #[error("JSON parsing error: {0}")]
    JsonParse(String),

    #[error("Unsupported provider: {0}")]
    UnsupportedProvider(String),
}

impl LlmError {
    /// Convert a reqwest error to an appropriate LlmError variant.
    pub fn from_reqwest(e: &reqwest::Error, timeout_secs: u64) -> Self {
        if e.is_timeout() {
            LlmError::Timeout(timeout_secs)
        } else {
            LlmError::Network(e.to_string())
        }
    }
}

pub type Result<T> = std::result::Result<T, LlmError>;
