use axum::{
    http::{header::CONTENT_TYPE, StatusCode},
    response::{IntoResponse, Response},
    routing::get,
    Json, Router,
};

use super::content;
use super::types::ContentConfig;

/// Build a router with all discovery endpoints. Can be merged into the main app.
pub fn discovery_routes(config: ContentConfig) -> Router {
    Router::new()
        // Text discovery
        .route("/ai.txt", get(ai_txt))
        .route("/llms.txt", get(llms_txt))
        .route("/llms-full.txt", get(llms_full_txt))
        .route("/llms-admin.txt", get(llms_admin_txt))
        // Agent & skill guides
        .route("/agent.md", get(agent_md))
        .route("/skill.md", get(skill_md))
        .route("/skill.json", get(skill_json))
        .route("/skills/sanctions.md", get(skill_sanctions_md))
        // Health
        .route("/heartbeat.md", get(heartbeat_md))
        .route("/heartbeat.json", get(heartbeat_json))
        // Standard manifests
        .route("/.well-known/ai-discovery.json", get(ai_discovery_json))
        .route("/.well-known/ai-plugin.json", get(ai_plugin_json))
        .route("/.well-known/agent.json", get(agent_json))
        .route("/.well-known/mcp", get(mcp_json))
        // OpenAPI
        .route("/openapi.json", get(openapi_json))
        .with_state(config)
}

// --- Text endpoints ---

async fn ai_txt(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Response {
    text_response(content::generate_ai_txt(&c))
}

async fn llms_txt(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Response {
    text_response(content::generate_llms_txt(&c))
}

async fn llms_full_txt(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Response {
    text_response(content::generate_llms_full_txt(&c))
}

async fn llms_admin_txt(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Response {
    text_response(content::generate_llms_admin_txt(&c))
}

// --- Markdown endpoints ---

async fn agent_md(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Response {
    markdown_response(content::generate_agent_md(&c))
}

async fn skill_md(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Response {
    markdown_response(content::generate_skill_md(&c))
}

async fn skill_sanctions_md(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Response {
    markdown_response(content::generate_skill_sanctions_md(&c))
}

async fn heartbeat_md(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Response {
    markdown_response(content::generate_heartbeat_md(&c))
}

// --- JSON endpoints ---

async fn skill_json(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Json<serde_json::Value> {
    Json(serde_json::to_value(content::build_skill_metadata(&c)).expect("serialize"))
}

async fn heartbeat_json(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Json<serde_json::Value> {
    Json(serde_json::to_value(content::build_heartbeat(&c)).expect("serialize"))
}

async fn ai_discovery_json(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Json<serde_json::Value> {
    Json(serde_json::to_value(content::build_discovery_index(&c)).expect("serialize"))
}

async fn ai_plugin_json(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Json<serde_json::Value> {
    Json(serde_json::to_value(content::build_ai_plugin_manifest(&c)).expect("serialize"))
}

async fn agent_json(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Json<serde_json::Value> {
    Json(serde_json::to_value(content::build_agent_card(&c)).expect("serialize"))
}

async fn mcp_json(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Json<serde_json::Value> {
    Json(serde_json::to_value(content::build_mcp_discovery(&c)).expect("serialize"))
}

async fn openapi_json(
    axum::extract::State(c): axum::extract::State<ContentConfig>,
) -> Json<serde_json::Value> {
    Json(content::build_openapi_spec(&c))
}

// --- Helpers ---

fn text_response(body: String) -> Response {
    (
        StatusCode::OK,
        [(CONTENT_TYPE, "text/plain; charset=utf-8")],
        body,
    )
        .into_response()
}

fn markdown_response(body: String) -> Response {
    (
        StatusCode::OK,
        [(CONTENT_TYPE, "text/markdown; charset=utf-8")],
        body,
    )
        .into_response()
}
