//! HTTP and Validation Errors

use axum::http::StatusCode;
use thiserror::Error;

/// HTTP and validation specific errors
#[derive(Error, Debug, Clone)]
pub enum HttpError {
    /// Validation errors
    #[error("Validation error: {0}")]
    Validation(String),

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

    /// Conflict (e.g., duplicate resources)
    #[error("Conflict: {0}")]
    Conflict(String),

    /// Bad request
    #[error("Bad request: {0}")]
    BadRequest(String),

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

    /// WebSocket errors
    #[error("WebSocket error: {0}")]
    WebSocket(String),
}

impl HttpError {
    pub fn status_code(&self) -> StatusCode {
        match self {
            Self::Validation(_) => StatusCode::BAD_REQUEST,
            Self::NotFound(_) => StatusCode::NOT_FOUND,
            Self::Conflict(_) => StatusCode::CONFLICT,
            Self::BadRequest(_) => StatusCode::BAD_REQUEST,
            Self::RateLimit(_) => StatusCode::TOO_MANY_REQUESTS,
            Self::WebSocket(_) => StatusCode::BAD_REQUEST,
        }
    }

    pub fn error_code(&self) -> &'static str {
        match self {
            Self::Validation(_) => "VALIDATION_ERROR",
            Self::NotFound(_) => "NOT_FOUND",
            Self::Conflict(_) => "CONFLICT",
            Self::BadRequest(_) => "BAD_REQUEST",
            Self::RateLimit(_) => "RATE_LIMIT_EXCEEDED",
            Self::WebSocket(_) => "WEBSOCKET_ERROR",
        }
    }
}

// Conversions from external validation errors
impl From<validator::ValidationErrors> for HttpError {
    fn from(errors: validator::ValidationErrors) -> Self {
        let details = errors
            .field_errors()
            .iter()
            .map(|(field, errors)| {
                let messages: Vec<String> = errors
                    .iter()
                    .filter_map(|e| e.message.as_ref().map(|m| m.to_string()))
                    .collect();
                (field.to_string(), messages)
            })
            .collect::<std::collections::HashMap<_, _>>();

        Self::Validation(format!("Validation failed: {:?}", details))
    }
}

// Helper functions for creating common HTTP errors
pub fn bad_request(message: &str) -> HttpError {
    HttpError::BadRequest(message.to_string())
}

pub fn conflict(message: &str) -> HttpError {
    HttpError::Conflict(message.to_string())
}

pub fn not_found(message: &str) -> HttpError {
    HttpError::NotFound(message.to_string())
}
