mod bootstrap;

use std::sync::Arc;

use bootstrap::{EmbeddingRuntimeRole, init, prepare_embedding_runtime};
use ingestion_pipeline::{pipeline::IngestionPipeline, run_worker_loop};
use tracing::info;

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    let services = init().await?;
    // The worker owns re-embedding: it reconciles stored vectors to the active provider.
    prepare_embedding_runtime(&services, EmbeddingRuntimeRole::Maintainer).await?;

    info!(
        embedding_backend = ?services.config.embedding_backend,
        "Embedding provider initialized for worker"
    );

    let ingestion_pipeline = Arc::new(IngestionPipeline::new(
        Arc::clone(&services.db),
        Arc::clone(&services.openai_client),
        services.config.clone(),
        services.reranker_pool.clone(),
        services.storage,
        Arc::clone(&services.embedding_provider),
    )?);

    run_worker_loop(
        services.db,
        ingestion_pipeline,
        services.config.index_rebuild_interval_secs,
    )
    .await
}

#[cfg(test)]
mod tests {
    use std::sync::Arc;
    use std::time::Duration;

    use chrono::Utc;
    use common::storage::types::ingestion_task::{DEFAULT_LEASE_SECS, IngestionTask};
    use ingestion_pipeline::pipeline::IngestionPipeline;

    use crate::bootstrap::tests::init_smoke_services;

    #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
    async fn worker_smoke_initializes_and_claims_idle() -> anyhow::Result<()> {
        let (services, data_dir) = init_smoke_services().await?;

        let pipeline = IngestionPipeline::new(
            Arc::clone(&services.db),
            Arc::clone(&services.openai_client),
            services.config.clone(),
            services.reranker_pool.clone(),
            services.storage,
            Arc::clone(&services.embedding_provider),
        )?;

        let worker_id = "worker-smoke";
        let claimed = IngestionTask::claim_next_ready(
            &services.db,
            worker_id,
            Utc::now(),
            Duration::from_secs(DEFAULT_LEASE_SECS as u64),
        )
        .await?;
        assert!(
            claimed.is_none(),
            "worker smoke test should find no pending tasks"
        );

        let db = Arc::clone(&services.db);
        let pipeline = Arc::new(pipeline);
        let worker =
            tokio::spawn(async move { ingestion_pipeline::run_worker_loop(db, pipeline, 0).await });

        tokio::time::sleep(Duration::from_millis(250)).await;
        assert!(
            !worker.is_finished(),
            "worker loop should keep running while idle"
        );
        worker.abort();

        tokio::fs::remove_dir_all(&data_dir).await.ok();
        Ok(())
    }
}
