use std::time::Duration;

use axum::{Router, error_handling::HandleErrorLayer, response::IntoResponse};
use tower::{ServiceBuilder, timeout::TimeoutLayer};

use crate::rest::{RestError, response::ApiResponse};

/// Applies a timeout layer and maps elapsed requests into uniform responses.
pub fn apply_timeout(router: Router, duration: Duration) -> Router {
    router.layer(
        ServiceBuilder::new()
            .layer(HandleErrorLayer::new(|error: tower::BoxError| async move {
                if error.is::<tower::timeout::error::Elapsed>() {
                    RestError::Timeout.into_response()
                } else {
                    ApiResponse::<()>::fail("INTERNAL", error.to_string()).into_response()
                }
            }))
            .layer(TimeoutLayer::new(duration)),
    )
}
