use std::sync::Arc;

use tokio::net::TcpListener;
use tracing::{info, warn};
use vapora_a2a::{
    agent_card::generate_default_agent_card, bridge::CoordinatorBridge, server::create_router,
    server::A2aState, task_manager::TaskManager,
};
use vapora_agents::{
    config::AgentConfig,
    coordinator::AgentCoordinator,
    nats_bridge::{NatsBridge, NatsBrokerConfig},
    registry::AgentRegistry,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        .init();

    let args: Vec<String> = std::env::args().collect();

    let host = args
        .iter()
        .zip(args.iter().skip(1))
        .find(|(k, _)| *k == "--host")
        .map(|(_, v)| v.as_str())
        .unwrap_or("127.0.0.1");

    let port = args
        .iter()
        .zip(args.iter().skip(1))
        .find(|(k, _)| *k == "--port")
        .map(|(_, v)| v.as_str())
        .unwrap_or("8003");

    let version = args
        .iter()
        .zip(args.iter().skip(1))
        .find(|(k, _)| *k == "--version")
        .map(|(_, v)| v.as_str())
        .unwrap_or("1.0.0");

    let nats_url =
        std::env::var("NATS_URL").unwrap_or_else(|_| "nats://127.0.0.1:4222".to_string());
    let surreal_url = std::env::var("SURREAL_URL").unwrap_or_else(|_| "127.0.0.1:8000".to_string());

    let addr = format!("{}:{}", host, port);

    info!("Starting VAPORA A2A Server on {}", addr);

    // Connect to SurrealDB
    info!(url = %surreal_url, "Connecting to SurrealDB");
    let db =
        surrealdb::Surreal::new::<surrealdb::engine::remote::ws::Ws>(surreal_url.as_str()).await?;

    db.signin(surrealdb::opt::auth::Root {
        username: "root".to_string(),
        password: "root".to_string(),
    })
    .await?;

    db.use_ns("vapora").use_db("main").await?;
    info!("Connected to SurrealDB");

    let registry = Arc::new(AgentRegistry::new(10));

    // Connect to NATS via NatsBridge (JetStream, durable) — graceful fallback
    let nats_bridge = {
        let config = NatsBrokerConfig {
            url: nats_url.clone(),
            ..NatsBrokerConfig::default()
        };
        match NatsBridge::connect(config, registry.clone()).await {
            Ok(bridge) => {
                info!(url = %nats_url, "NatsBridge connected (JetStream)");
                Some(Arc::new(bridge))
            }
            Err(e) => {
                warn!(
                    error = %e,
                    "Failed to connect NatsBridge; result listener and JetStream dispatch disabled"
                );
                None
            }
        }
    };

    let task_manager = Arc::new(TaskManager::new(db.clone()));
    let config = AgentConfig::default();
    let agent_coordinator = Arc::new(AgentCoordinator::new(config, registry).await?);

    let bridge = Arc::new(CoordinatorBridge::new(
        agent_coordinator.clone(),
        task_manager.clone(),
        nats_bridge,
    ));

    // Start JetStream result listener
    bridge.start_result_listener().await?;

    let agent_card =
        generate_default_agent_card(format!("http://{}:{}", host, port), version.to_string())?;

    let state = A2aState {
        task_manager,
        bridge,
        agent_card,
    };

    let router = create_router(state);

    let listener = TcpListener::bind(&addr).await?;
    info!("A2A Server listening on http://{}", addr);

    axum::serve(listener, router).await?;

    Ok(())
}
