//! Health check endpoints for ML training service
//!
//! Provides HTTP-based health and readiness endpoints that don't require TLS,
//! allowing Docker Compose / Kubernetes health checks to work without client certificates.
//!
//! The readiness probe validates that the training orchestrator has fully initialized
//! before Kubernetes routes traffic to this instance.

use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;

use axum::{extract::State, routing::get, Json, Router};
use serde::Serialize;

/// Shared health state for readiness probing.
///
/// The `ready` flag is set to `true` once the training orchestrator has started
/// successfully. Until then, the `/ready` endpoint returns `"not_ready"` so that
/// Kubernetes does not route traffic to an instance that cannot serve requests.
#[derive(Clone)]
pub struct HealthState {
    /// Whether the service is ready to accept requests.
    pub ready: Arc<AtomicBool>,
}

/// Health status response
#[derive(Serialize)]
pub struct HealthResponse {
    /// Service status
    pub status: &'static str,
    /// Service name
    pub service: &'static str,
    /// Service version
    pub version: &'static str,
}

/// Creates the health check router with /health and /ready endpoints
pub fn health_router(state: HealthState) -> Router {
    Router::new()
        .route("/health", get(health_check))
        .route("/ready", get(readiness_check))
        .with_state(state)
}

/// Liveness probe - indicates service process is running.
///
/// This intentionally does NOT check any downstream dependencies. If this
/// handler can execute, the process is alive — which is exactly what a
/// Kubernetes liveness probe should verify.
async fn health_check() -> Json<HealthResponse> {
    Json(HealthResponse {
        status: "healthy",
        service: "ml_training",
        version: env!("CARGO_PKG_VERSION"),
    })
}

/// Readiness probe - indicates service is ready to accept requests.
///
/// Returns `"ready"` only when the training orchestrator has fully initialized.
/// Before that, returns `"not_ready"` so Kubernetes will not route traffic here.
async fn readiness_check(State(state): State<HealthState>) -> Json<HealthResponse> {
    let status = if state.ready.load(Ordering::Relaxed) {
        "ready"
    } else {
        "not_ready"
    };
    Json(HealthResponse {
        status,
        service: "ml_training",
        version: env!("CARGO_PKG_VERSION"),
    })
}
