use axum::{
    routing::{delete, get, post},
    Router,
};
use provisioning_orchestrator::{compliance_routes, webhooks::{handle_webhook, WebhookState, WorkspaceRegistry}};
use std::sync::Arc;
use tower_http::cors::CorsLayer;

use crate::{
    api_catalog,
    handlers::{
        audit::{
            apply_audit_retention, export_audit_logs, get_audit_stats, get_audit_storage_stats,
            query_audit_logs, search_audit_logs,
        },
        batch::{
            cancel_batch_operation, execute_batch_operation, get_batch_operation_status,
            list_batch_operations,
        },
        extensions::{
            get_services_status, list_dns_records, list_loaded_extensions, list_oci_artifacts,
            list_services, reload_extension,
        },
        rollback::{
            create_checkpoint, execute_rollback, get_checkpoint, get_rollback_statistics,
            list_checkpoints, restore_from_checkpoint,
        },
        state::{
            get_state_statistics, get_system_health, get_system_metrics, get_workflow_progress,
            get_workflow_snapshots,
        },
        tasks::{get_task_status, health_check, list_tasks},
        test_env::{
            cleanup_test_environment, create_test_environment, get_environment_logs,
            get_test_environment, list_test_environments, run_environment_tests,
        },
        vm_pool::{destroy_runner, get_p95, record_build_metrics, spawn_runner},
        workflows::{
            create_cluster_workflow, create_component_workflow, create_server_workflow,
            create_taskserv_workflow,
        },
    },
};

pub fn build_router(state: Arc<provisioning_orchestrator::AppState>) -> Router {
    let webhook_state = Arc::new(WebhookState {
        registry: Arc::new(parking_lot::RwLock::new(WorkspaceRegistry::new())),
    });

    let app = Router::new()
        .route("/api/v1/catalog", get(api_catalog::api_catalog))
        .route("/health", get(health_check))
        .route("/api/v1/health", get(health_check))
        .route("/tasks", get(list_tasks))
        .route("/tasks/{id}", get(get_task_status))
        .route("/workflows/servers/create", post(create_server_workflow))
        .route("/workflows/taskserv/create", post(create_taskserv_workflow))
        .route("/workflows/cluster/create", post(create_cluster_workflow))
        .route(
            "/api/v1/workflows/component/{operation}",
            post(create_component_workflow),
        )
        // Batch operation routes
        .route("/batch/execute", post(execute_batch_operation))
        .route("/batch/operations", get(list_batch_operations))
        .route("/batch/operations/{id}", get(get_batch_operation_status))
        .route(
            "/batch/operations/{id}/cancel",
            post(cancel_batch_operation),
        )
        // State management routes
        .route("/state/workflows/{id}/progress", get(get_workflow_progress))
        .route(
            "/state/workflows/{id}/snapshots",
            get(get_workflow_snapshots),
        )
        .route("/state/system/metrics", get(get_system_metrics))
        .route("/state/system/health", get(get_system_health))
        .route("/state/statistics", get(get_state_statistics))
        // Rollback and recovery routes
        .route("/rollback/checkpoints", post(create_checkpoint))
        .route("/rollback/checkpoints", get(list_checkpoints))
        .route("/rollback/checkpoints/{id}", get(get_checkpoint))
        .route("/rollback/execute", post(execute_rollback))
        .route("/rollback/restore/{id}", post(restore_from_checkpoint))
        .route("/rollback/statistics", get(get_rollback_statistics))
        // Test environment routes
        .route("/test/environments/create", post(create_test_environment))
        .route("/test/environments", get(list_test_environments))
        .route("/test/environments/{id}", get(get_test_environment))
        .route("/test/environments/{id}/run", post(run_environment_tests))
        .route(
            "/test/environments/{id}",
            axum::routing::delete(cleanup_test_environment),
        )
        .route("/test/environments/{id}/logs", get(get_environment_logs))
        // DNS integration routes
        .route("/api/v1/dns/records", get(list_dns_records))
        // Extension loading routes
        .route("/api/v1/extensions/loaded", get(list_loaded_extensions))
        .route("/api/v1/extensions/reload", post(reload_extension))
        // OCI registry routes
        .route("/api/v1/oci/artifacts", post(list_oci_artifacts))
        // Service orchestration routes
        .route("/api/v1/services/list", get(list_services))
        .route("/api/v1/services/status", get(get_services_status))
        // VM pool routes (ephemeral buildkit runners — ADR-039)
        .route("/api/v1/vm-pool/spawn", post(spawn_runner))
        .route("/api/v1/vm-pool/{lease_id}", delete(destroy_runner))
        .route("/api/v1/vm-pool/p95/{workspace}", get(get_p95))
        .route("/api/v1/vm-pool/metrics", post(record_build_metrics))
        // Audit logging routes
        .route("/api/v1/audit/query", post(query_audit_logs))
        .route("/api/v1/audit/export", post(export_audit_logs))
        .route("/api/v1/audit/stats", get(get_audit_stats))
        .route("/api/v1/audit/storage-stats", get(get_audit_storage_stats))
        .route("/api/v1/audit/apply-retention", post(apply_audit_retention))
        .route("/api/v1/audit/search", post(search_audit_logs))
        // Compliance routes
        .nest(
            "/api/v1/compliance",
            compliance_routes(state.compliance_service.clone()),
        )
        // Merge monitoring routes (includes /metrics, /ws, /events)
        .merge(state.monitoring_system.create_routes())
        // Webhook handler (separate state — workspace registry)
        .route(
            "/api/v1/webhooks/{workspace_id}",
            post(handle_webhook).with_state(webhook_state),
        )
        .layer(CorsLayer::permissive())
        .with_state(state.clone());

    // Infra reconcile endpoint — only compiled when the `nats` feature is active.
    // Must be registered on a fresh router that still holds a state reference.
    #[cfg(feature = "nats")]
    let app = {
        use crate::handlers::infra::trigger_infra_reconcile;
        app.merge(
            Router::new()
                .route("/api/v1/infra/reconcile", post(trigger_infra_reconcile))
                .with_state(state),
        )
    };

    app
}
