use axum::{routing::get, Router};
use indexer::{api, AppState};
use sqlx::postgres::PgPoolOptions;
use stripstream_core::config::IndexerConfig;
use tracing::info;

fn main() -> anyhow::Result<()> {
    // Limit blocking thread pool to 8 threads (default 512).
    // Each spawn_blocking call (archive extraction, image save) gets a thread.
    // With thousands of books, unlimited threads cause OOM via stack memory (~8MB each).
    let runtime = tokio::runtime::Builder::new_multi_thread()
        .enable_all()
        .max_blocking_threads(8)
        .build()?;
    runtime.block_on(async_main())
}

async fn async_main() -> anyhow::Result<()> {
    tracing_subscriber::fmt()
        .with_env_filter(
            std::env::var("RUST_LOG").unwrap_or_else(|_| {
                "indexer=info,axum=info,scan=info,extraction=info,thumbnail=warn,watcher=info".to_string()
            }),
        )
        .init();

    let config = IndexerConfig::from_env()?;
    let pool = PgPoolOptions::new()
        .max_connections(20)
        .connect(&config.database_url)
        .await?;

    let state = AppState { pool };

    tokio::spawn(indexer::worker::run_worker(state.clone(), config.scan_interval_seconds));

    let app = Router::new()
        .route("/health", get(api::health))
        .route("/version", get(api::version))
        .route("/ready", get(api::ready))
        .with_state(state.clone());

    let listener = tokio::net::TcpListener::bind(&config.listen_addr).await?;
    info!(addr = %config.listen_addr, "indexer listening");
    axum::serve(listener, app).await?;
    Ok(())
}
