use anyhow::Result;
use axum::{Router, routing::get};
use std::net::SocketAddr;
use tracing::{error, info};

use llm_proxy::{
    config::AppConfig,
    dashboard, database,
    providers::ProviderManager,
    rate_limiting::{CircuitBreakerConfig, RateLimitManager, RateLimiterConfig},
    server,
    state::AppState,
    utils::crypto,
};

#[tokio::main]
async fn main() -> Result<()> {
    // Initialize tracing (logging)
    tracing_subscriber::fmt()
        .with_max_level(tracing::Level::INFO)
        .with_target(false)
        .init();

    info!("Starting LLM Proxy Gateway v{}", env!("CARGO_PKG_VERSION"));

    // Load configuration
    let config = AppConfig::load().await?;
    info!("Configuration loaded from {:?}", config.config_path);

    // Initialize encryption
    crypto::init_with_key(&config.encryption_key)?;
    info!("Encryption initialized");

    // Initialize database connection pool
    let db_pool = database::init(&config.database).await?;
    info!("Database initialized at {:?}", config.database.path);

    // Initialize provider manager with configured providers
    let provider_manager = ProviderManager::new();

    // Initialize all supported providers (they handle their own enabled check)
    let supported_providers = vec!["openai", "gemini", "deepseek", "grok", "ollama"];
    for name in supported_providers {
        if let Err(e) = provider_manager.initialize_provider(name, &config, &db_pool).await {
            error!("Failed to initialize provider {}: {}", name, e);
        }
    }

    // Create rate limit manager
    let rate_limit_manager = RateLimitManager::new(RateLimiterConfig::default(), CircuitBreakerConfig::default());

    // Fetch model registry from models.dev
    let model_registry = match llm_proxy::utils::registry::fetch_registry().await {
        Ok(registry) => registry,
        Err(e) => {
            error!("Failed to fetch model registry: {}. Using empty registry.", e);
            llm_proxy::models::registry::ModelRegistry {
                providers: std::collections::HashMap::new(),
            }
        }
    };

    // Create application state
    let state = AppState::new(
        config.clone(),
        provider_manager,
        db_pool,
        rate_limit_manager,
        model_registry,
        config.server.auth_tokens.clone(),
    );

    // Initialize model config cache and start background refresh (every 30s)
    state.model_config_cache.refresh().await;
    state.model_config_cache.clone().start_refresh_task(30);
    info!("Model config cache initialized");

    // Create application router
    let app = Router::new()
        .route("/health", get(health_check))
        .merge(server::router(state.clone()))
        .merge(dashboard::router(state.clone()));

    // Start server
    let addr = SocketAddr::from(([0, 0, 0, 0], config.server.port));
    info!("Server listening on http://{}", addr);

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

    Ok(())
}

async fn health_check() -> &'static str {
    "OK"
}
