//! CLI port of `scripts/scrape_nl_comps.py` — KVK → `nl_companies` + `global_companies_registry`.

use std::path::PathBuf;
use std::sync::Arc;
use std::time::Duration;

use clap::Parser;
use dexter_sentinel::scrape::nl::{run_nl_randomized_loop, run_nl_single_pass, NlScrapeConfig};
use dexter_sentinel::scrape::DexterAthena;

#[derive(Parser, Debug)]
#[command(
    name = "nl-scrape",
    about = "Scrape purely Dutch company schemas from KVK API"
)]
#[command(group(
    clap::ArgGroup::new("query_mode")
        .required(true)
        .args(["query", "randomize_query"])
))]
struct Cli {
    /// Output CSV containing parsed `nl_companies` formatted rows
    #[arg(short = 'o', long, default_value = "nl_companies.csv")]
    output: PathBuf,

    /// Specific company name or fragment to search for
    #[arg(short = 'q', long)]
    query: Option<String>,

    /// URL to the specific KVK JSON API
    #[arg(long, default_value = "https://web-api.kvk.nl/zoeken/v3/search")]
    kvk_api_url: String,

    /// URL for the Dexter Athena Gateway
    #[arg(long, default_value = "https://cluster.athena-db.com")]
    athena_url: String,

    /// API key for the Dexter Athena Gateway (also uses ATHENA_API_KEY env)
    #[arg(long, env = "ATHENA_API_KEY")]
    athena_key: Option<String>,

    /// Value of the X-Athena-Client header
    #[arg(long, default_value = "dexter")]
    athena_client: String,

    /// Optional X-User-Id header for the Athena Gateway inserts
    #[arg(long, env = "ATHENA_USER_ID")]
    athena_user_id: Option<String>,

    /// Optional X-Company-Id header for the Athena Gateway inserts
    #[arg(long, env = "ATHENA_COMPANY_ID")]
    athena_company_id: Option<String>,

    /// Optional X-Organization-Id header for the Athena Gateway inserts
    #[arg(long, env = "ATHENA_ORGANIZATION_ID")]
    athena_organization_id: Option<String>,

    /// Print function timing and memory telemetry output (if instrumented)
    #[arg(long, default_value_t = false)]
    telemetry: bool,

    /// Dry run: scrape and save locally but do not upload to Athena
    #[arg(long, default_value_t = false)]
    no_insert: bool,

    /// Max concurrent network inserts targeting Athena
    #[arg(long, default_value_t = 25)]
    max_workers: usize,

    /// Enable recursive continuous scraping by using the incoming dataset to generate random queries
    #[arg(short = 'r', long, default_value_t = false)]
    randomize_query: bool,

    /// Maximum string length when randomly slicing company names for the next query
    #[arg(long, default_value_t = 2)]
    max_query_length: usize,
}

#[tokio::main]
async fn main() -> anyhow::Result<()> {
    dotenv::dotenv().ok();
    tracing_subscriber::fmt()
        .with_env_filter(
            tracing_subscriber::EnvFilter::try_from_default_env()
                .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("info")),
        )
        .init();

    let cli = Cli::parse();
    let insert = !cli.no_insert;

    let dexter = if insert {
        let key = cli
            .athena_key
            .filter(|s| !s.is_empty())
            .or_else(|| std::env::var("ATHENA_API_KEY").ok())
            .filter(|s| !s.is_empty())
            .ok_or_else(|| {
                anyhow::anyhow!("set --athena-key or ATHENA_API_KEY when not using --no-insert")
            })?;
        Some(Arc::new(
            DexterAthena::from_cli(
                &cli.athena_url,
                &key,
                &cli.athena_client,
                cli.athena_user_id.clone(),
                cli.athena_company_id.clone(),
                cli.athena_organization_id.clone(),
                None,
            )
            .await?,
        ))
    } else {
        None
    };

    if cli.telemetry {
        dexter_sentinel::scrape::log::TELEMETRY.store(true, std::sync::atomic::Ordering::Relaxed);
        dexter_sentinel::scrape::log::rate_reset();
        tokio::spawn(async {
            dexter_sentinel::scrape::log::rate_logger_loop_nl().await;
        });
    }

    let http = reqwest::Client::builder()
        .timeout(Duration::from_secs(60))
        .build()?;

    let cfg = NlScrapeConfig {
        output_csv: cli.output.clone(),
        kvk_api_url: cli.kvk_api_url.clone(),
        insert,
        max_workers: cli.max_workers,
        max_query_len: cli.max_query_length,
    };

    if cli.randomize_query {
        tracing::info!("nl-scrape: randomized loop");
        run_nl_randomized_loop(http, dexter, cfg).await
    } else {
        let q = cli.query.unwrap_or_default();
        let q = q.trim();
        tracing::info!("nl-scrape: single query");
        run_nl_single_pass(&http, dexter, &cfg, q).await
    }
}
