// Swarm API endpoints for task coordination and agent management
// Phase 5.2: SwarmCoordinator integration with REST API

use std::sync::Arc;

use axum::{
    extract::Extension, http::StatusCode, response::IntoResponse, routing::get, Json, Router,
};
use ontoref_derive::onto_api;
use serde::{Deserialize, Serialize};
use tracing::info;
use vapora_swarm::coordinator::SwarmCoordinator;

#[derive(Serialize, Deserialize, Clone)]
pub struct SwarmStatsResponse {
    pub total_agents: u32,
    pub available_agents: u32,
    pub avg_load: f64,
    pub active_tasks: u32,
    pub active_coalitions: u32,
}

#[derive(Serialize)]
pub struct HealthResponse {
    pub status: String,
    pub agents_count: u32,
}

#[allow(dead_code)]
pub fn swarm_routes() -> Router {
    Router::new()
        .route("/swarm/stats", get(swarm_statistics))
        .route("/swarm/health", get(swarm_health))
}

/// Get swarm statistics
#[onto_api(
    method = "GET",
    path = "/api/v1/swarm/stats",
    description = "Returns live swarm statistics including agent counts, average load, and active \
                   tasks.",
    auth = "bearer",
    actors = "developer, agent, ci, admin",
    tags = "swarm, read"
)]
pub async fn swarm_statistics(
    Extension(swarm): Extension<Arc<SwarmCoordinator>>,
) -> impl IntoResponse {
    let stats = swarm.get_swarm_stats();

    info!(
        "Swarm stats: {} total agents, {} available, {:.2}% avg load",
        stats.total_agents,
        stats.available_agents,
        stats.avg_load * 100.0
    );

    (
        StatusCode::OK,
        Json(SwarmStatsResponse {
            total_agents: stats.total_agents,
            available_agents: stats.available_agents,
            avg_load: stats.avg_load,
            active_tasks: stats.active_tasks,
            active_coalitions: stats.active_coalitions,
        }),
    )
}

/// Get swarm health status
#[onto_api(
    method = "GET",
    path = "/api/v1/swarm/health",
    description = "Returns the overall health status of the swarm based on agent availability.",
    auth = "bearer",
    actors = "developer, agent, ci, admin",
    tags = "swarm, health, read"
)]
pub async fn swarm_health(Extension(swarm): Extension<Arc<SwarmCoordinator>>) -> impl IntoResponse {
    let stats = swarm.get_swarm_stats();

    let status = if stats.total_agents > 0 && stats.available_agents > 0 {
        "healthy"
    } else if stats.total_agents > 0 {
        "degraded"
    } else {
        "no_agents"
    };

    (
        StatusCode::OK,
        Json(HealthResponse {
            status: status.to_string(),
            agents_count: stats.total_agents,
        }),
    )
}

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

    #[tokio::test]
    async fn test_swarm_stats_response_structure() {
        let response = SwarmStatsResponse {
            total_agents: 10,
            available_agents: 8,
            avg_load: 0.5,
            active_tasks: 5,
            active_coalitions: 2,
        };

        assert_eq!(response.total_agents, 10);
        assert_eq!(response.available_agents, 8);
        assert_eq!(response.active_tasks, 5);
    }

    #[tokio::test]
    async fn test_health_response_structure() {
        let response = HealthResponse {
            status: "healthy".to_string(),
            agents_count: 5,
        };

        assert_eq!(response.status, "healthy");
        assert_eq!(response.agents_count, 5);
    }
}
