//! HTTP middleware for request/response processing

use crate::errors::Result;
use crate::http::{HttpRequest, HttpResponse};
use async_trait::async_trait;
use std::sync::Arc;

/// Middleware trait for processing requests and responses
#[async_trait]
pub trait Middleware: Send + Sync {
    /// Process request before handler
    async fn before_request(&self, _request: &mut HttpRequest) -> Result<()> {
        Ok(())
    }

    /// Process response after handler
    async fn after_response(&self, _response: &mut HttpResponse) -> Result<()> {
        Ok(())
    }
}

/// CORS middleware
pub struct CorsMiddleware {
    allowed_origins: Vec<String>,
    allowed_methods: Vec<String>,
    allowed_headers: Vec<String>,
}

impl CorsMiddleware {
    /// Create new CORS middleware
    pub fn new() -> Self {
        Self {
            allowed_origins: vec!["*".to_string()],
            allowed_methods: vec![
                "GET".to_string(),
                "POST".to_string(),
                "PUT".to_string(),
                "DELETE".to_string(),
                "OPTIONS".to_string(),
            ],
            allowed_headers: vec!["Content-Type".to_string(), "Authorization".to_string()],
        }
    }

    /// Set allowed origins
    pub fn allow_origins(mut self, origins: Vec<String>) -> Self {
        self.allowed_origins = origins;
        self
    }
}

#[async_trait]
impl Middleware for CorsMiddleware {
    async fn after_response(&self, response: &mut HttpResponse) -> Result<()> {
        // Add CORS headers
        let origin = self.allowed_origins.join(", ");
        let methods = self.allowed_methods.join(", ");
        let headers = self.allowed_headers.join(", ");

        if let Ok(name) = http::header::HeaderName::try_from("access-control-allow-origin") {
            if let Ok(value) = http::header::HeaderValue::try_from(origin) {
                response.headers.insert(name, value);
            }
        }

        if let Ok(name) = http::header::HeaderName::try_from("access-control-allow-methods") {
            if let Ok(value) = http::header::HeaderValue::try_from(methods) {
                response.headers.insert(name, value);
            }
        }

        if let Ok(name) = http::header::HeaderName::try_from("access-control-allow-headers") {
            if let Ok(value) = http::header::HeaderValue::try_from(headers) {
                response.headers.insert(name, value);
            }
        }

        Ok(())
    }
}

/// Compression middleware
pub struct CompressionMiddleware {
    min_size: usize,
}

impl CompressionMiddleware {
    /// Create new compression middleware
    pub fn new(min_size: usize) -> Self {
        Self { min_size }
    }
}

#[async_trait]
impl Middleware for CompressionMiddleware {
    async fn after_response(&self, response: &mut HttpResponse) -> Result<()> {
        // Only compress if body is large enough
        if response.body_len().unwrap_or(0) >= self.min_size {
            // TODO: Implement actual compression
            if let Ok(name) = http::header::HeaderName::try_from("content-encoding") {
                if let Ok(value) = http::header::HeaderValue::try_from("gzip") {
                    response.headers.insert(name, value);
                }
            }
        }
        Ok(())
    }
}

/// Rate limiting middleware
pub struct RateLimitMiddleware {
    max_requests: usize,
    window_secs: u64,
}

impl RateLimitMiddleware {
    /// Create new rate limit middleware
    pub fn new(max_requests: usize, window_secs: u64) -> Self {
        Self {
            max_requests,
            window_secs,
        }
    }
}

#[async_trait]
impl Middleware for RateLimitMiddleware {
    async fn before_request(&self, _request: &mut HttpRequest) -> Result<()> {
        // TODO: Implement actual rate limiting
        Ok(())
    }
}

/// Middleware chain for composing multiple middleware
pub struct MiddlewareChain {
    middlewares: Vec<Arc<dyn Middleware>>,
}

impl MiddlewareChain {
    /// Create empty middleware chain
    pub fn new() -> Self {
        Self {
            middlewares: Vec::new(),
        }
    }

    /// Add middleware to chain
    pub fn add(mut self, middleware: Arc<dyn Middleware>) -> Self {
        self.middlewares.push(middleware);
        self
    }

    /// Process request through all middleware
    pub async fn process_request(&self, request: &mut HttpRequest) -> Result<()> {
        for middleware in &self.middlewares {
            middleware.before_request(request).await?;
        }
        Ok(())
    }

    /// Process response through all middleware (in reverse)
    pub async fn process_response(&self, response: &mut HttpResponse) -> Result<()> {
        for middleware in self.middlewares.iter().rev() {
            middleware.after_response(response).await?;
        }
        Ok(())
    }
}

impl Default for MiddlewareChain {
    fn default() -> Self {
        Self::new()
    }
}
