// vapora-backend: REST API server for VAPORA v1.0
// Phase 1: Complete backend with SurrealDB integration

mod api;
mod audit;
mod config;
mod services;
mod workflow;

use std::net::SocketAddr;
use std::sync::Arc;

use anyhow::Result;
use axum::{
    routing::{delete, get, post, put},
    Extension, Router,
};
use tower_http::cors::{Any, CorsLayer};
use tracing::{info, Level};
use vapora_swarm::{SwarmCoordinator, SwarmMetrics};

use crate::api::AppState;
use crate::config::Config;
use crate::services::{AgentService, ProjectService, ProviderAnalyticsService, TaskService};

#[tokio::main]
async fn main() -> Result<()> {
    // Load environment variables from .env file if present
    dotenv::dotenv().ok();

    // Initialize logging
    tracing_subscriber::fmt()
        .with_max_level(Level::INFO)
        .with_target(false)
        .compact()
        .init();

    info!("VAPORA Backend v{}", env!("CARGO_PKG_VERSION"));
    info!("Phase 1: Backend Core + SurrealDB");

    // Load configuration
    let config = Config::load("config/vapora.toml")?;
    info!("Configuration loaded successfully");

    // Connect to SurrealDB via WebSocket
    info!("Connecting to SurrealDB at {}", config.database.url);
    let db =
        surrealdb::Surreal::new::<surrealdb::engine::remote::ws::Ws>(&config.database.url).await?;

    // Sign in to database
    db.signin(surrealdb::opt::auth::Root {
        username: "root",
        password: "root",
    })
    .await?;

    // Use namespace and database
    db.use_ns("vapora").use_db("main").await?;
    info!("Connected to SurrealDB");

    // Initialize services
    let project_service = ProjectService::new(db.clone());
    let task_service = TaskService::new(db.clone());
    let agent_service = AgentService::new(db.clone());
    let provider_analytics_service = ProviderAnalyticsService::new(db.clone());

    // Create KG Persistence for analytics
    let kg_persistence = Arc::new(vapora_knowledge_graph::KGPersistence::new(db.clone()));

    // Create application state
    let app_state = AppState::new(
        project_service,
        task_service,
        agent_service,
        provider_analytics_service,
    );

    // Create SwarmMetrics for Prometheus monitoring
    let metrics = match SwarmMetrics::new() {
        Ok(m) => {
            info!("SwarmMetrics initialized for Prometheus monitoring");
            m
        }
        Err(e) => {
            tracing::warn!(
                "Failed to initialize SwarmMetrics: {:?}, continuing without metrics",
                e
            );
            // Create new registry and metrics as fallback
            SwarmMetrics::new().unwrap()
        }
    };

    // Create SwarmCoordinator for multi-agent coordination
    let mut swarm_coordinator = SwarmCoordinator::new();
    swarm_coordinator.set_metrics(Arc::clone(&metrics));
    let swarm_coordinator = Arc::new(swarm_coordinator);
    info!("SwarmCoordinator initialized for Phase 5.2");

    // Initialize analytics metrics (Phase 6)
    api::analytics_metrics::register_analytics_metrics();
    info!("Analytics metrics registered for Prometheus");

    // Initialize provider metrics (Phase 7)
    api::provider_metrics::register_provider_metrics();
    info!("Provider metrics registered for Prometheus");

    // Start metrics collector background task (Phase 6)
    let metrics_collector =
        api::metrics_collector::MetricsCollector::new(kg_persistence.clone(), 60);
    let _collector_handle = metrics_collector.start();
    info!("Metrics collector started (60s interval)");

    // Configure CORS
    let cors = CorsLayer::new()
        .allow_origin(Any)
        .allow_methods(Any)
        .allow_headers(Any);

    // Build router
    let app = Router::new()
        // Health endpoint
        .route("/health", get(api::health::health))
        // Metrics endpoint (Prometheus)
        .route("/metrics", get(api::metrics::metrics_handler))
        // Project endpoints
        .route(
            "/api/v1/projects",
            get(api::projects::list_projects).post(api::projects::create_project),
        )
        .route(
            "/api/v1/projects/:id",
            get(api::projects::get_project)
                .put(api::projects::update_project)
                .delete(api::projects::delete_project),
        )
        .route(
            "/api/v1/projects/:id/features",
            post(api::projects::add_feature),
        )
        .route(
            "/api/v1/projects/:id/features/:feature",
            delete(api::projects::remove_feature),
        )
        .route(
            "/api/v1/projects/:id/archive",
            post(api::projects::archive_project),
        )
        // Task endpoints
        .route(
            "/api/v1/tasks",
            get(api::tasks::list_tasks).post(api::tasks::create_task),
        )
        .route(
            "/api/v1/tasks/:id",
            get(api::tasks::get_task)
                .put(api::tasks::update_task)
                .delete(api::tasks::delete_task),
        )
        .route("/api/v1/tasks/:id/reorder", put(api::tasks::reorder_task))
        .route(
            "/api/v1/tasks/:id/status",
            put(api::tasks::update_task_status),
        )
        .route("/api/v1/tasks/:id/assign", put(api::tasks::assign_task))
        .route(
            "/api/v1/tasks/:id/priority",
            put(api::tasks::update_priority),
        )
        // Agent endpoints (specific routes before parameterized routes)
        .route(
            "/api/v1/agents",
            get(api::agents::list_agents).post(api::agents::register_agent),
        )
        .route(
            "/api/v1/agents/available",
            get(api::agents::get_available_agents),
        )
        .route(
            "/api/v1/agents/:id",
            get(api::agents::get_agent)
                .put(api::agents::update_agent)
                .delete(api::agents::deregister_agent),
        )
        .route(
            "/api/v1/agents/:id/health",
            get(api::agents::check_agent_health),
        )
        .route(
            "/api/v1/agents/:id/status",
            put(api::agents::update_agent_status),
        )
        .route(
            "/api/v1/agents/:id/capabilities",
            post(api::agents::add_capability),
        )
        .route(
            "/api/v1/agents/:id/capabilities/:capability",
            delete(api::agents::remove_capability),
        )
        .route("/api/v1/agents/:id/skills", post(api::agents::add_skill))
        // Tracking endpoints
        .route(
            "/api/v1/tracking/entries",
            get(api::tracking::list_tracking_entries),
        )
        .route(
            "/api/v1/tracking/summary",
            get(api::tracking::get_tracking_summary),
        )
        .route(
            "/api/v1/tracking/health",
            get(api::tracking::tracking_health),
        )
        // Swarm endpoints (Phase 5.2)
        .route("/api/v1/swarm/stats", get(api::swarm::swarm_statistics))
        .route("/api/v1/swarm/health", get(api::swarm::swarm_health))
        // Analytics endpoints (Phase 6)
        .route(
            "/api/v1/analytics/agent/:id",
            get(api::analytics::get_agent_performance),
        )
        .route(
            "/api/v1/analytics/task-types/:task_type",
            get(api::analytics::get_task_type_analytics),
        )
        .route(
            "/api/v1/analytics/dashboard",
            get(api::analytics::get_dashboard_metrics),
        )
        .route(
            "/api/v1/analytics/cost-report",
            get(api::analytics::get_cost_report),
        )
        .route(
            "/api/v1/analytics/summary",
            get(api::analytics::get_analytics_summary),
        )
        // Provider analytics endpoints (Phase 7)
        .route(
            "/api/v1/analytics/providers",
            get(api::provider_analytics::get_provider_cost_breakdown),
        )
        .route(
            "/api/v1/analytics/providers/efficiency",
            get(api::provider_analytics::get_provider_efficiency),
        )
        .route(
            "/api/v1/analytics/providers/:provider",
            get(api::provider_analytics::get_provider_analytics),
        )
        .route(
            "/api/v1/analytics/providers/:provider/forecast",
            get(api::provider_analytics::get_provider_forecast),
        )
        .route(
            "/api/v1/analytics/providers/:provider/tasks/:task_type",
            get(api::provider_analytics::get_provider_task_type_metrics),
        )
        // Apply CORS, state, and extensions
        .layer(Extension(swarm_coordinator))
        .layer(cors)
        .with_state(app_state);

    // Start server
    let addr = SocketAddr::from(([127, 0, 0, 1], config.server.port));
    info!("Server listening on {}", addr);
    info!("Health check: http://{}/health", addr);
    info!("API documentation: http://{}/api/v1", addr);

    let listener = tokio::net::TcpListener::bind(addr).await?;
    axum::serve(listener, app).await?;

    Ok(())
}
