//! Common API handlers
//!
//! Health check and OpenAPI specification endpoints.

use axum::{extract::State, http::StatusCode, response::IntoResponse, Json};
use serde_json::json;
use syntaxis_core::persistence::Database;

use crate::state::AppState;

/// Initialize server uptime tracking
///
/// Must be called once at application startup
pub fn init_uptime() {
    shared_api_lib::health::init_uptime();
}

/// Health check endpoint with database status
pub async fn health(State(state): State<AppState>) -> Json<serde_json::Value> {
    let db_healthy = state.db.ping().await.is_ok();
    let uptime = shared_api_lib::health::get_uptime();
    let uptime_formatted = shared_api_lib::health::format_uptime(uptime);

    Json(json!({
        "status": if db_healthy { "healthy" } else { "unhealthy" },
        "service": "syntaxis-api",
        "version": "0.1.0",
        "uptime": {
            "seconds": uptime,
            "formatted": uptime_formatted
        },
        "database": {
            "connected": db_healthy,
            "type": "sqlite"
        },
        "timestamp": chrono::Utc::now().to_rfc3339()
    }))
}

/// Metrics endpoint handler
pub async fn metrics_handler(State(state): State<AppState>) -> impl IntoResponse {
    match state.metrics.gather_metrics() {
        Ok(metrics) => (StatusCode::OK, metrics).into_response(),
        Err(_e) => {
            tracing::error!("Failed to gather metrics");
            (
                StatusCode::INTERNAL_SERVER_ERROR,
                "Failed to gather metrics",
            )
                .into_response()
        }
    }
}

/// OpenAPI specification endpoint
pub async fn openapi_spec() -> Json<serde_json::Value> {
    Json(crate::openapi::generate_openapi_spec())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_init_uptime() {
        init_uptime();
        let _uptime = shared_api_lib::health::get_uptime();
        // If we got here without panicking, initialization worked
    }

    #[test]
    fn test_uptime_formatting() {
        let formatted = shared_api_lib::health::format_uptime(3661);
        assert!(formatted.contains("h"));
    }
}
