//! Error types for the Provisioning MCP Server

use thiserror::Error;

#[derive(Error, Debug)]
pub enum ProvisioningError {
    #[error("Invalid input: {0}")]
    InvalidInput(String),

    #[error("Provisioning command failed: {0}")]
    CommandFailed(String),

    #[error("AI service error: {0}")]
    AIServiceError(String),

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

    #[error("Infrastructure not found: {0}")]
    InfrastructureNotFound(String),

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

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

    #[error("IO error: {0}")]
    IoError(#[from] std::io::Error),

    #[error("JSON error: {0}")]
    JsonError(#[from] serde_json::Error),

    #[error("HTTP error: {0}")]
    HttpError(#[from] reqwest::Error),

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

impl ProvisioningError {
    /// Create a new invalid input error
    pub fn invalid_input<S: Into<String>>(msg: S) -> Self {
        Self::InvalidInput(msg.into())
    }

    /// Create a new command failed error
    pub fn command_failed<S: Into<String>>(msg: S) -> Self {
        Self::CommandFailed(msg.into())
    }

    /// Create a new AI service error
    pub fn ai_service_error<S: Into<String>>(msg: S) -> Self {
        Self::AIServiceError(msg.into())
    }

    /// Create a new configuration error
    pub fn config_error<S: Into<String>>(msg: S) -> Self {
        Self::ConfigError(msg.into())
    }

    /// Check if error is recoverable
    pub fn is_recoverable(&self) -> bool {
        match self {
            Self::InvalidInput(_) => true,
            Self::CommandFailed(_) => false,
            Self::AIServiceError(_) => true,
            Self::ConfigError(_) => false,
            Self::InfrastructureNotFound(_) => true,
            Self::ServiceUnavailable(_) => true,
            Self::ParseError(_) => true,
            Self::IoError(_) => false,
            Self::JsonError(_) => true,
            Self::HttpError(_) => true,
            Self::ValidationError(_) => true,
        }
    }

    /// Get error category for logging
    pub fn category(&self) -> &'static str {
        match self {
            Self::InvalidInput(_) => "input",
            Self::CommandFailed(_) => "command",
            Self::AIServiceError(_) => "ai",
            Self::ConfigError(_) => "config",
            Self::InfrastructureNotFound(_) => "infrastructure",
            Self::ServiceUnavailable(_) => "service",
            Self::ParseError(_) => "parse",
            Self::IoError(_) => "io",
            Self::JsonError(_) => "json",
            Self::HttpError(_) => "http",
            Self::ValidationError(_) => "validation",
        }
    }
}
