//! Health check endpoints.

use axum::{extract::State, routing::get, Json, Router};
use std::time::Instant;

use crate::{
    response::{HealthResponse, HealthStatus, ServiceHealth},
    routes::AppState,
};

/// Build health routes.
pub fn router() -> Router<AppState> {
    Router::new()
        .route("/health", get(health_check))
        .route("/health/live", get(liveness))
        .route("/health/ready", get(readiness))
}

/// Basic health check.
#[utoipa::path(
    get,
    path = "/health",
    responses(
        (status = 200, description = "Service is healthy", body = HealthResponse)
    ),
    tag = "Health"
)]
async fn health_check(State(_state): State<AppState>) -> Json<HealthResponse> {
    // Get uptime (would come from server state in production)
    let uptime_seconds = 0; // Placeholder

    Json(HealthResponse {
        status: HealthStatus::Healthy,
        version: env!("CARGO_PKG_VERSION").to_string(),
        uptime_seconds,
        services: None,
    })
}

/// Liveness probe (for Kubernetes).
#[utoipa::path(
    get,
    path = "/health/live",
    responses(
        (status = 200, description = "Service is alive")
    ),
    tag = "Health"
)]
async fn liveness() -> &'static str {
    "OK"
}

/// Readiness probe with service checks.
#[utoipa::path(
    get,
    path = "/health/ready",
    responses(
        (status = 200, description = "Service is ready", body = HealthResponse),
        (status = 503, description = "Service is not ready")
    ),
    tag = "Health"
)]
async fn readiness(State(state): State<AppState>) -> Json<HealthResponse> {
    let mut services = Vec::new();
    let mut overall_status = HealthStatus::Healthy;

    // Check RPC service
    let rpc_health = check_service_health("rpc", &state.config.services.rpc).await;
    if rpc_health.status != HealthStatus::Healthy {
        overall_status = HealthStatus::Degraded;
    }
    services.push(rpc_health);

    // Check other services...
    // In production, we'd check all backend services

    Json(HealthResponse {
        status: overall_status,
        version: env!("CARGO_PKG_VERSION").to_string(),
        uptime_seconds: 0,
        services: Some(services),
    })
}

/// Check health of a backend service.
async fn check_service_health(name: &str, _endpoint: &str) -> ServiceHealth {
    let start = Instant::now();

    // Attempt to connect to the service
    // In production, this would make an actual health check request
    let is_healthy = true; // Placeholder

    ServiceHealth {
        name: name.to_string(),
        status: if is_healthy {
            HealthStatus::Healthy
        } else {
            HealthStatus::Unhealthy
        },
        message: None,
        latency_ms: Some(start.elapsed().as_millis() as u64),
    }
}
