// Agents API endpoints

use axum::{
    extract::{Path, State},
    http::StatusCode,
    response::IntoResponse,
    Json,
};
use serde::Deserialize;
use vapora_shared::models::{Agent, AgentStatus};

use crate::api::state::AppState;
use crate::api::ApiResult;

#[derive(Debug, Deserialize)]
pub struct UpdateStatusPayload {
    pub status: AgentStatus,
}

#[derive(Debug, Deserialize)]
pub struct CapabilityPayload {
    pub capability: String,
}

#[derive(Debug, Deserialize)]
pub struct SkillPayload {
    pub skill: String,
}

/// List all agents
///
/// GET /api/v1/agents
pub async fn list_agents(State(state): State<AppState>) -> ApiResult<impl IntoResponse> {
    let agents = state.agent_service.list_agents().await?;
    Ok(Json(agents))
}

/// Get a specific agent
///
/// GET /api/v1/agents/:id
pub async fn get_agent(
    State(state): State<AppState>,
    Path(id): Path<String>,
) -> ApiResult<impl IntoResponse> {
    let agent = state.agent_service.get_agent(&id).await?;
    Ok(Json(agent))
}

/// Register a new agent
///
/// POST /api/v1/agents
pub async fn register_agent(
    State(state): State<AppState>,
    Json(agent): Json<Agent>,
) -> ApiResult<impl IntoResponse> {
    let created = state.agent_service.register_agent(agent).await?;
    Ok((StatusCode::CREATED, Json(created)))
}

/// Update an agent
///
/// PUT /api/v1/agents/:id
pub async fn update_agent(
    State(state): State<AppState>,
    Path(id): Path<String>,
    Json(updates): Json<Agent>,
) -> ApiResult<impl IntoResponse> {
    let updated = state.agent_service.update_agent(&id, updates).await?;
    Ok(Json(updated))
}

/// Deregister an agent
///
/// DELETE /api/v1/agents/:id
pub async fn deregister_agent(
    State(state): State<AppState>,
    Path(id): Path<String>,
) -> ApiResult<impl IntoResponse> {
    state.agent_service.deregister_agent(&id).await?;
    Ok(StatusCode::NO_CONTENT)
}

/// Update agent status
///
/// PUT /api/v1/agents/:id/status
pub async fn update_agent_status(
    State(state): State<AppState>,
    Path(id): Path<String>,
    Json(payload): Json<UpdateStatusPayload>,
) -> ApiResult<impl IntoResponse> {
    let updated = state
        .agent_service
        .update_agent_status(&id, payload.status)
        .await?;
    Ok(Json(updated))
}

/// Add capability to agent
///
/// POST /api/v1/agents/:id/capabilities
pub async fn add_capability(
    State(state): State<AppState>,
    Path(id): Path<String>,
    Json(payload): Json<CapabilityPayload>,
) -> ApiResult<impl IntoResponse> {
    let updated = state
        .agent_service
        .add_capability(&id, payload.capability)
        .await?;
    Ok(Json(updated))
}

/// Remove capability from agent
///
/// DELETE /api/v1/agents/:id/capabilities/:capability
pub async fn remove_capability(
    State(state): State<AppState>,
    Path((id, capability)): Path<(String, String)>,
) -> ApiResult<impl IntoResponse> {
    let updated = state
        .agent_service
        .remove_capability(&id, &capability)
        .await?;
    Ok(Json(updated))
}

/// Add skill to agent
///
/// POST /api/v1/agents/:id/skills
pub async fn add_skill(
    State(state): State<AppState>,
    Path(id): Path<String>,
    Json(payload): Json<SkillPayload>,
) -> ApiResult<impl IntoResponse> {
    let updated = state.agent_service.add_skill(&id, payload.skill).await?;
    Ok(Json(updated))
}

/// Get available agents
///
/// GET /api/v1/agents/available
pub async fn get_available_agents(State(state): State<AppState>) -> ApiResult<impl IntoResponse> {
    let agents = state.agent_service.get_available_agents().await?;
    Ok(Json(agents))
}

/// Check agent health
///
/// GET /api/v1/agents/:id/health
pub async fn check_agent_health(
    State(state): State<AppState>,
    Path(id): Path<String>,
) -> ApiResult<impl IntoResponse> {
    let is_healthy = state.agent_service.check_agent_health(&id).await?;
    Ok(Json(serde_json::json!({
        "agent_id": id,
        "healthy": is_healthy
    })))
}
