//! LLM Gateway error types (Phase-78)

use thiserror::Error;

/// Errors that can occur in the LLM Gateway.
#[derive(Debug, Error)]
pub enum LlmError {
    /// Provider not found
    #[error("Provider not found: {0}")]
    ProviderNotFound(String),

    /// Model not found
    #[error("Model not found: {0}")]
    ModelNotFound(String),

    /// Provider is not healthy / unreachable
    #[error("Provider unhealthy: {0}")]
    ProviderUnhealthy(String),

    /// All providers failed (after failover attempts)
    #[error("All providers failed for model '{model}': {details}")]
    AllProvidersFailed {
        model: String,
        details: String,
    },

    /// API request error (HTTP level)
    #[error("API request error: {0}")]
    RequestError(String),

    /// API response parsing error
    #[error("API response parse error: {0}")]
    ResponseParseError(String),

    /// Authentication error (invalid/missing API key)
    #[error("Authentication error: {0}")]
    AuthError(String),

    /// Rate limit exceeded
    #[error("Rate limit exceeded: {0}")]
    RateLimitExceeded(String),

    /// Token limit exceeded
    #[error("Token limit exceeded: max={max}, requested={requested}")]
    TokenLimitExceeded {
        max: usize,
        requested: usize,
    },

    /// Stream error
    #[error("Stream error: {0}")]
    StreamError(String),

    /// Configuration error
    #[error("Configuration error: {0}")]
    ConfigError(String),

    /// Serialization / deserialization error
    #[error("Serialization error: {0}")]
    SerializationError(String),

    /// Storage error (CRUD operations)
    #[error("Storage error: {0}")]
    StorageError(String),

    /// Encryption/decryption error (API key storage)
    #[error("Encryption error: {0}")]
    EncryptionError(String),

    /// Unsupported capability
    #[error("Unsupported capability: {capability} by provider '{provider}'")]
    UnsupportedCapability {
        capability: String,
        provider: String,
    },

    /// Conversation not found
    #[error("Conversation not found: {0}")]
    ConversationNotFound(String),

    /// Generation cancelled by user
    #[error("Generation cancelled")]
    Cancelled,

    /// Unsupported protocol
    #[error("Unsupported protocol: {0}")]
    UnsupportedProtocol(String),

    /// All providers unavailable (all unhealthy + within cooldown)
    #[error("All providers unavailable: {0}")]
    AllProvidersUnavailable(String),

    /// Permission denied (ownership / visibility violation)
    #[error("Permission denied: {0}")]
    PermissionDenied(String),

    /// Resource not found (generic)
    #[error("Not found: {0}")]
    NotFound(String),

    /// Invalid input (bad arguments, missing required fields)
    #[error("Invalid input: {0}")]
    InvalidInput(String),

    /// Internal error (unexpected)
    #[error("Internal LLM error: {0}")]
    Internal(String),
}

/// Result type alias for LLM operations.
pub type LlmResult<T> = Result<T, LlmError>;

// ── Conversions ──────────────────────────────────────────────

impl From<serde_json::Error> for LlmError {
    fn from(e: serde_json::Error) -> Self {
        LlmError::SerializationError(e.to_string())
    }
}

impl From<std::io::Error> for LlmError {
    fn from(e: std::io::Error) -> Self {
        LlmError::Internal(format!("IO error: {e}"))
    }
}
