pub mod graphql;
pub mod media;

use axum::{
    extract::State,
    http::StatusCode,
    response::IntoResponse,
    routing::get,
    Json, Router,
};
use serde::Serialize;

use crate::db::Database;

pub use graphql::{graphql_handler, graphql_playground};
pub use media::{get_media, head_media, MediaState};

#[derive(Serialize)]
struct HealthResponse {
    status: &'static str,
    version: &'static str,
}

#[derive(Serialize)]
struct ReadyResponse {
    status: &'static str,
    version: &'static str,
    database: &'static str,
}

/// Basic liveness check - is the process running?
async fn health() -> impl IntoResponse {
    Json(HealthResponse {
        status: "ok",
        version: env!("CARGO_PKG_VERSION"),
    })
}

/// Readiness check - can we actually serve requests?
/// Tests database connectivity to catch stale credentials.
async fn ready(State(db): State<Database>) -> impl IntoResponse {
    let pool = db.pool().await;

    match sqlx::query("SELECT 1").execute(&*pool).await {
        Ok(_) => (
            StatusCode::OK,
            Json(ReadyResponse {
                status: "ok",
                version: env!("CARGO_PKG_VERSION"),
                database: "connected",
            }),
        ),
        Err(e) => {
            tracing::error!(error = %e, "Health check failed: database connection error");
            (
                StatusCode::SERVICE_UNAVAILABLE,
                Json(ReadyResponse {
                    status: "error",
                    version: env!("CARGO_PKG_VERSION"),
                    database: "disconnected",
                }),
            )
        }
    }
}

pub fn router(db: Database) -> Router {
    Router::new()
        .route("/health", get(health))
        .route("/health/ready", get(ready))
        .with_state(db)
}
