use axum::{
    extract::DefaultBodyLimit,
    middleware,
    routing::{get, post},
    Router,
};
use std::sync::Arc;

use super::{
    auth, get_issue_workflow_by_issue, get_issue_workflow_by_pr, get_project_workflow_by_project,
    get_task, get_task_artifacts, get_task_prompts, get_task_proof, get_workflow_runtime_tree,
    github_webhook, handle_rpc, health_check, ingest_signal, intake_status, list_tasks,
    password_reset, project_queue_stats, state::AppState, stream_task_sse, task_mutation_routes,
    task_routes,
};

pub(super) fn build_router(state: Arc<AppState>) -> Router {
    Router::new()
        .route("/", get(crate::dashboard::index))
        .route("/overview", get(crate::overview::index))
        .route("/usage", get(crate::dashboard::index))
        .route("/worktrees", get(crate::dashboard::index))
        .route(
            "/assets/{filename}",
            axum::routing::get(crate::assets::serve),
        )
        .route("/favicon.ico", get(crate::dashboard::favicon))
        .route("/health", get(health_check))
        .route("/rpc", post(handle_rpc))
        .route("/ws", get(crate::websocket::ws_handler))
        .route("/tasks", post(task_routes::create_task))
        .route("/tasks", get(list_tasks))
        .route("/tasks/batch", post(task_routes::create_tasks_batch))
        .route("/tasks/{id}", get(get_task))
        .route("/tasks/{id}/cancel", post(task_routes::cancel_task))
        .route("/tasks/{id}/merge", post(task_mutation_routes::merge_task))
        .route("/tasks/{id}/artifacts", get(get_task_artifacts))
        .route("/tasks/{id}/prompts", get(get_task_prompts))
        .route("/tasks/{id}/proof", get(get_task_proof))
        .route("/tasks/{id}/stream", get(stream_task_sse))
        .route(
            "/projects",
            post(crate::handlers::projects::register_project)
                .get(crate::handlers::projects::list_projects),
        )
        .route(
            "/projects/{id}",
            get(crate::handlers::projects::get_project)
                .delete(crate::handlers::projects::delete_project),
        )
        .route("/projects/queue-stats", get(project_queue_stats))
        .route("/api/dashboard", get(crate::handlers::dashboard::dashboard))
        .route("/api/overview", get(crate::handlers::overview::overview))
        .route("/api/worktrees", get(crate::handlers::worktrees::worktrees))
        .route(
            "/api/operator-snapshot",
            get(crate::handlers::operator_snapshot::operator_snapshot),
        )
        .route("/api/intake", get(intake_status))
        .route(
            "/api/workflows/issues/by-issue",
            get(get_issue_workflow_by_issue),
        )
        .route("/api/workflows/issues/by-pr", get(get_issue_workflow_by_pr))
        .route(
            "/api/workflows/projects/by-project",
            get(get_project_workflow_by_project),
        )
        .route(
            "/api/workflows/runtime/tree",
            get(get_workflow_runtime_tree),
        )
        .route(
            "/api/workflows/runtime/merge",
            post(task_mutation_routes::merge_workflow_runtime),
        )
        .route(
            "/api/workflows/runtime/cancel",
            post(task_mutation_routes::cancel_workflow_runtime),
        )
        .route(
            "/api/runtime-hosts",
            get(crate::handlers::runtime_hosts::list_runtime_hosts),
        )
        .route(
            "/api/runtime-hosts/register",
            post(crate::handlers::runtime_hosts::register_runtime_host),
        )
        .route(
            "/api/runtime-hosts/{host_id}/heartbeat",
            post(crate::handlers::runtime_hosts::heartbeat_runtime_host),
        )
        .route(
            "/api/runtime-hosts/{host_id}/deregister",
            post(crate::handlers::runtime_hosts::deregister_runtime_host),
        )
        .route(
            "/api/runtime-hosts/{host_id}/tasks/claim",
            post(crate::handlers::runtime_hosts::claim_task_for_runtime_host),
        )
        .route(
            "/api/runtime-hosts/{host_id}/runtime-jobs/claim",
            post(crate::handlers::runtime_hosts::claim_runtime_job_for_runtime_host),
        )
        .route(
            "/api/runtime-hosts/{host_id}/runtime-jobs/{runtime_job_id}/complete",
            post(crate::handlers::runtime_hosts::complete_runtime_job_for_runtime_host),
        )
        .route(
            "/api/runtime-hosts/{host_id}/projects",
            get(crate::handlers::runtime_project_cache::list_runtime_host_projects),
        )
        .route(
            "/api/runtime-hosts/{host_id}/projects/sync",
            post(crate::handlers::runtime_project_cache::sync_runtime_host_projects),
        )
        .route(
            "/api/token-usage",
            get(crate::handlers::token_usage::token_usage),
        )
        .route(
            "/api/usage-monitor",
            get(crate::handlers::usage_monitor::usage_monitor),
        )
        .route(
            "/api/evals/runs",
            post(crate::handlers::evals::create_eval_run)
                .get(crate::handlers::evals::list_eval_runs),
        )
        .route(
            "/api/evals/runs/{run_id}",
            get(crate::handlers::evals::get_eval_run),
        )
        .route(
            "/api/evals/runs/{run_id}/artifacts",
            post(crate::handlers::evals::add_eval_artifact)
                .get(crate::handlers::evals::list_eval_artifacts),
        )
        .route(
            "/api/evals/runs/{run_id}/score",
            post(crate::handlers::evals::score_eval_run),
        )
        .route(
            "/api/evals/quality-snapshots/{snapshot_id}",
            get(crate::handlers::evals::get_eval_quality_snapshot),
        )
        .route(
            "/api/evals/pr/{owner}/{repo}/{pr_number}",
            get(crate::handlers::evals::list_eval_quality_snapshots_for_pr),
        )
        .route(
            "/webhook",
            post(github_webhook).layer(DefaultBodyLimit::max(
                state.core.server.config.server.max_webhook_body_bytes,
            )),
        )
        .route(
            "/webhook/feishu",
            post(crate::intake::feishu::feishu_webhook).layer(DefaultBodyLimit::max(
                state.core.server.config.server.max_webhook_body_bytes,
            )),
        )
        .route(
            "/signals",
            post(ingest_signal).layer(DefaultBodyLimit::max(
                state.core.server.config.server.max_webhook_body_bytes,
            )),
        )
        .route("/auth/reset-password", post(password_reset))
        .route("/reconcile", post(crate::handlers::reconcile::handle))
        .layer(middleware::from_fn_with_state(
            state.clone(),
            auth::api_auth_middleware,
        ))
        .with_state(state)
}
