//! Rate limiting middleware using tower-governor
//!
//! Protects against brute force attacks on authentication endpoints.

use tower_governor::{
    governor::GovernorConfigBuilder,
    GovernorLayer,
};

/// Create rate limiting layer for authentication endpoints
///
/// Allows 5 requests per minute per IP address
pub fn auth_rate_limiter() -> impl tower::Layer<tower::service_fn::ServiceFn<impl Fn(axum::http::Request<axum::body::Body>) -> std::future::Future<Output = Result<axum::http::Response<axum::body::Body>, std::convert::Infallible>>>> {
    let governor_conf = Box::new(
        GovernorConfigBuilder::default()
            .per_millisecond(60000 / 5) // 5 requests per minute
            .burst_size(5)
            .finish()
            .unwrap()
    );

    GovernorLayer {
        config: Box::leak(governor_conf),
    }
}

/// Create rate limiting layer for support code validation
///
/// Allows 10 requests per minute per IP address
pub fn support_code_rate_limiter() -> impl tower::Layer<tower::service_fn::ServiceFn<impl Fn(axum::http::Request<axum::body::Body>) -> std::future::Future<Output = Result<axum::http::Response<axum::body::Body>, std::convert::Infallible>>>> {
    let governor_conf = Box::new(
        GovernorConfigBuilder::default()
            .per_millisecond(60000 / 10) // 10 requests per minute
            .burst_size(10)
            .finish()
            .unwrap()
    );

    GovernorLayer {
        config: Box::leak(governor_conf),
    }
}

/// Create rate limiting layer for API endpoints
///
/// Allows 60 requests per minute per IP address
pub fn api_rate_limiter() -> impl tower::Layer<tower::service_fn::ServiceFn<impl Fn(axum::http::Request<axum::body::Body>) -> std::future::Future<Output = Result<axum::http::Response<axum::body::Body>, std::convert::Infallible>>>> {
    let governor_conf = Box::new(
        GovernorConfigBuilder::default()
            .per_millisecond(1000) // 1 request per second
            .burst_size(60)
            .finish()
            .unwrap()
    );

    GovernorLayer {
        config: Box::leak(governor_conf),
    }
}
