#[cfg(feature = "http")]
use std::sync::Arc;

#[cfg(feature = "http")]
use axum::{
    http::{
        header::{self, HeaderValue},
        Method,
    },
    middleware as axum_mw,
    routing::get,
    Router,
};
#[cfg(feature = "http")]
use tower_http::{cors::CorsLayer, trace::TraceLayer};

#[cfg(feature = "http")]
use crate::handlers;
#[cfg(feature = "http")]
use crate::middleware::api_key::api_key_middleware;
#[cfg(feature = "http")]
use crate::AppState;

/// Build the axum router with all routes and middleware.
///
/// Public routes (no auth):
/// - `GET /v1/lists` — flat sanctions list (addresses + country codes)
///
/// Authenticated routes (require `X-API-Key` header):
/// - `GET /v1/check/{currency}?address=<addr>` — check a specific address
#[cfg(feature = "http")]
pub(crate) fn build_router(state: Arc<AppState>, cors_origins: &[String]) -> Router {
    // Authenticated check endpoint.
    let check_routes = Router::new()
        .route("/check/{currency}", get(handlers::check_address))
        .layer(axum_mw::from_fn_with_state(
            state.clone(),
            api_key_middleware,
        ))
        .with_state(state.clone());

    // Public lists endpoint (no auth).
    let lists_route = Router::new()
        .route("/lists", get(handlers::sanctions_lists))
        .with_state(state.clone());

    let mut app = Router::new()
        .nest("/v1", lists_route.merge(check_routes))
        .layer(TraceLayer::new_for_http());

    if let Some(cors_layer) = build_cors_layer(cors_origins) {
        app = app.layer(cors_layer);
    }

    app
}

#[cfg(feature = "http")]
fn build_cors_layer(origins: &[String]) -> Option<CorsLayer> {
    if origins.is_empty() {
        return None;
    }

    if origins.iter().any(|o| o == "*") {
        return Some(
            CorsLayer::new()
                .allow_origin(tower_http::cors::Any)
                .allow_methods([Method::GET, Method::OPTIONS])
                .allow_headers([header::CONTENT_TYPE, header::ACCEPT]),
        );
    }

    let header_values: Vec<HeaderValue> = origins
        .iter()
        .filter_map(|o| HeaderValue::from_str(o).ok())
        .collect();

    Some(
        CorsLayer::new()
            .allow_origin(header_values)
            .allow_methods([Method::GET, Method::OPTIONS])
            .allow_headers([header::CONTENT_TYPE, header::ACCEPT]),
    )
}
