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

use axum::Router;
use clap::Parser;
use extension_registry::{config::Config, ExtensionRegistry, API_VERSION, DEFAULT_PORT};
use tokio::net::TcpListener;

mod api_catalog;
mod handlers;
use handlers::{routes, AppState};

#[derive(Parser)]
#[command(name = "extension-registry")]
#[command(about = "OCI-compliant extension registry proxy", long_about = None)]
struct Cli {
    /// Configuration file path (highest priority)
    #[arg(short = 'c', long, env = "EXTENSION_REGISTRY_CONFIG")]
    config: Option<std::path::PathBuf>,

    /// Configuration directory (searches for extension-registry.ncl|toml|json)
    #[arg(long, env = "PROVISIONING_CONFIG_DIR")]
    config_dir: Option<std::path::PathBuf>,

    /// Deployment mode (solo, multiuser, cicd, enterprise)
    #[arg(short = 'm', long, env = "EXTENSION_REGISTRY_MODE")]
    mode: Option<String>,

    /// Host to bind to
    #[arg(long, default_value = "127.0.0.1")]
    host: String,

    /// Port to bind to
    #[arg(long, default_value_t = DEFAULT_PORT)]
    port: u16,

    /// Print all #[onto_api] registered routes as JSON and exit.
    /// Pipe to api-catalog-extension-registry.json: `just export-api-catalog`
    #[arg(long)]
    dump_api_catalog: bool,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    // Parse CLI arguments FIRST (so --help works before any other processing)
    let cli = Cli::parse();

    if cli.dump_api_catalog {
        println!("{}", ontoref_ontology::api::dump_catalog_json());
        return Ok(());
    }

    // Initialize centralized observability (logging, metrics, health checks)
    let _guard = observability::init_from_env("extension-registry", env!("CARGO_PKG_VERSION"))?;

    // Check if extension-registry is enabled in deployment-mode.ncl
    if let Ok(deployment) = platform_config::load_deployment_mode() {
        if let Ok(enabled) = deployment.is_service_enabled("extension_registry") {
            if !enabled {
                tracing::warn!("⚠ Extension Registry is DISABLED in deployment-mode.ncl");
                std::process::exit(1);
            }
            tracing::info!("✓ Extension Registry is ENABLED in deployment-mode.ncl");
        }
    }

    // Load configuration from Nickel or hierarchy
    let mut config = Config::load()?;

    // Apply CLI overrides if provided
    if !cli.host.is_empty() && cli.host != "0.0.0.0" {
        config.server.host = cli.host.clone();
    }
    if cli.port != 0 {
        config.server.port = cli.port;
    }

    tracing::info!(
        "🔧 Loaded extension-registry configuration (host: {}, port: {})",
        config.server.host,
        config.server.port
    );

    // Create registry service
    let addr: SocketAddr = format!("{}:{}", config.server.host, config.server.port).parse()?;
    let registry = Arc::new(ExtensionRegistry::new(addr));

    // Create application state
    let state = AppState::new(registry);

    // Build router
    let app: Router = routes(state);

    // Bind to address
    let listener = TcpListener::bind(addr).await?;

    tracing::info!(
        "extension-registry v{} starting on {} (OCI v2 API)",
        API_VERSION,
        addr
    );

    // Run server
    axum::serve(listener, app).await?;

    Ok(())
}
