//! Router assembly. Extracted from `main.rs` so integration tests can build the
//! exact same app (routes, middleware, layers) in process against a test
//! database instead of a live server.

use axum::{
    routing::{delete, get, post, put},
    Router,
};
use tower::ServiceBuilder;
use tower_http::{cors::CorsLayer, trace::TraceLayer};

use crate::config::AppState;
use crate::handlers;
use crate::middleware;

/// Compose the full Axum app: all public + protected routes, the JWT auth
/// layer on protected routes, and the global middleware stack (client-IP
/// resolution, security headers, rate limit, tracing, CORS).
///
/// `main.rs` calls this and wraps it in `into_make_service_with_connect_info`
/// before serving; tests call it and drive it with `oneshot`/`RouterExt`.
pub fn build_app(state: AppState) -> Router {
    // Build public routes (no auth required)
    let public_routes = Router::new()
        .route(
            "/health",
            get(handlers::health_check).head(handlers::health_check),
        )
        .route("/ready", get(handlers::ready_check))
        .route("/api/auth/register", post(handlers::register))
        .route("/api/auth/login", post(handlers::login))
        .route("/api/auth/refresh", post(handlers::refresh))
        .route("/api/auth/logout", post(handlers::logout))
        .route(
            "/api/auth/recover-password",
            post(handlers::recover_password),
        );

    // Build protected routes (auth required)
    let protected_routes = Router::new()
        // User profile management
        .route("/api/users/me", get(handlers::get_profile))
        .route("/api/users/me", put(handlers::update_profile))
        .route("/api/users/me", delete(handlers::delete_account))
        .route("/api/users/me/change-password", post(handlers::change_password))
        // User settings
        .route("/api/users/me/settings", get(handlers::get_settings))
        .route("/api/users/me/settings", put(handlers::update_settings))
        // Share management
        .route("/api/shares", post(handlers::create_share))
        .route("/api/shares", get(handlers::list_shares))
        .route("/api/shares/:id", put(handlers::update_share))
        .route("/api/shares/:id", delete(handlers::delete_share))
        // Permission checking
        .route("/api/permissions/check", post(handlers::check_permission))
        // Session management (Phase 2.6)
        .route("/api/sessions", get(handlers::get_sessions))
        .route("/api/sessions/:id", delete(handlers::revoke_session))
        .route("/api/sessions/all", delete(handlers::revoke_all_sessions))
        // Medication management (Phase 2.7)
        .route("/api/medications", post(handlers::create_medication))
        .route("/api/medications", get(handlers::list_medications))
        .route("/api/medications/:id", get(handlers::get_medication))
        .route("/api/medications/:id", post(handlers::update_medication))
        .route("/api/medications/:id/delete", post(handlers::delete_medication))
        .route("/api/medications/:id/log", post(handlers::log_dose))
        .route("/api/medications/:id/adherence", get(handlers::get_adherence))
        // Health statistics management (Phase 2.7)
        .route("/api/health-stats", post(handlers::create_health_stat))
        .route("/api/health-stats", get(handlers::list_health_stats))
        .route("/api/health-stats/trends", get(handlers::get_health_trends))
        .route("/api/health-stats/:id", get(handlers::get_health_stat))
        .route("/api/health-stats/:id", put(handlers::update_health_stat))
        .route("/api/health-stats/:id", delete(handlers::delete_health_stat))
        // Drug interactions (Phase 2.8)
        .route("/api/interactions/check", post(handlers::check_interactions))
        .route("/api/interactions/check-new", post(handlers::check_new_medication))
        .layer(axum::middleware::from_fn_with_state(
            state.clone(),
            middleware::jwt_auth_middleware,
        ));

    public_routes
        .merge(protected_routes)
        .with_state(state)
        .layer(
            ServiceBuilder::new()
                // Resolve the client IP once and stash it for handlers/middleware
                // (audit logging, account-lockout forensics).
                .layer(axum::middleware::from_fn(
                    middleware::client_ip_middleware,
                ))
                // Security headers (applies to all responses)
                .layer(axum::middleware::from_fn(
                    middleware::security_headers_middleware,
                ))
                // General rate limiting (currently a stub)
                .layer(axum::middleware::from_fn(
                    middleware::general_rate_limit_middleware,
                ))
                .layer(TraceLayer::new_for_http())
                .layer(CorsLayer::permissive()),
        )
}
