//! Templates API handler.

use axum::{extract::Query, http::StatusCode, response::IntoResponse, Json};
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;

use crate::llm::templates;
use crate::llm::templates::ContractTypeTemplate;

/// Query parameters for listing templates
#[derive(Debug, Deserialize, ToSchema)]
pub struct ListTemplatesQuery {
    /// Filter by contract phase (research, specify, plan, execute, review)
    pub phase: Option<String>,
}

/// Template summary for API response
#[derive(Debug, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct TemplateSummary {
    /// Template identifier
    pub id: String,
    /// Display name
    pub name: String,
    /// Contract phase this template is designed for
    pub phase: String,
    /// Brief description
    pub description: String,
    /// Number of body elements in the template
    pub element_count: usize,
}

/// Response for listing templates
#[derive(Debug, Serialize, ToSchema)]
pub struct ListTemplatesResponse {
    pub templates: Vec<TemplateSummary>,
}

/// List available file templates
#[utoipa::path(
    get,
    path = "/api/v1/templates",
    params(
        ("phase" = Option<String>, Query, description = "Filter by contract phase")
    ),
    responses(
        (status = 200, description = "Templates retrieved successfully", body = ListTemplatesResponse)
    ),
    tag = "templates"
)]
pub async fn list_templates(
    Query(query): Query<ListTemplatesQuery>,
) -> impl IntoResponse {
    let template_list = match query.phase.as_deref() {
        Some(phase) => templates::templates_for_phase(phase),
        None => templates::all_templates(),
    };

    let summaries: Vec<TemplateSummary> = template_list
        .iter()
        .map(|t| TemplateSummary {
            id: t.id.clone(),
            name: t.name.clone(),
            phase: t.phase.clone(),
            description: t.description.clone(),
            element_count: t.suggested_body.len(),
        })
        .collect();

    (
        StatusCode::OK,
        Json(ListTemplatesResponse {
            templates: summaries,
        }),
    )
        .into_response()
}

/// Get a specific template by ID
#[utoipa::path(
    get,
    path = "/api/v1/templates/{id}",
    params(
        ("id" = String, Path, description = "Template ID")
    ),
    responses(
        (status = 200, description = "Template retrieved successfully", body = templates::FileTemplate),
        (status = 404, description = "Template not found")
    ),
    tag = "templates"
)]
pub async fn get_template(
    axum::extract::Path(id): axum::extract::Path<String>,
) -> impl IntoResponse {
    let all = templates::all_templates();
    let template = all.into_iter().find(|t| t.id == id);

    match template {
        Some(t) => (StatusCode::OK, Json(serde_json::json!(t))).into_response(),
        None => (
            StatusCode::NOT_FOUND,
            Json(serde_json::json!({
                "error": format!("Template '{}' not found", id)
            })),
        )
            .into_response(),
    }
}

// =============================================================================
// Contract Type Templates (Workflow Definitions)
// =============================================================================

/// Response for listing contract types
#[derive(Debug, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct ListContractTypesResponse {
    pub contract_types: Vec<ContractTypeTemplate>,
}

/// List all available contract type templates
#[utoipa::path(
    get,
    path = "/api/v1/contract-types",
    responses(
        (status = 200, description = "Contract types retrieved successfully", body = ListContractTypesResponse)
    ),
    tag = "templates"
)]
pub async fn list_contract_types() -> impl IntoResponse {
    let contract_types = templates::all_contract_types();

    (
        StatusCode::OK,
        Json(ListContractTypesResponse { contract_types }),
    )
        .into_response()
}
