// Copyright (C) 2025  The Software Heritage developers
// See the AUTHORS file at the top-level directory of this distribution
// License: GNU General Public License version 3, or any later version
// See top-level LICENSE file for more information

use std::path::PathBuf;

use anyhow::{Context, Result};
use clap::Parser;
use swh_graph::graph::SwhUnidirectionalGraph;
use swh_graph::mph::DynMphf;

use swh_osv::commit2vuln::Commit2Vuln;

#[derive(Parser, Debug)]
struct Args {
    #[arg(long)]
    db: PathBuf,
    #[arg(long)]
    commit2vuln: PathBuf,
    #[arg(long)]
    graph: PathBuf,
    #[arg(long)]
    /// Path to the epserde-serialized `SubgraphWccs` written by `compute-connected-components`
    ///
    /// Must be provided if and only iff the file given as --commit2vuln was created using --subgraphwccs
    subgraphwccs: Option<PathBuf>,
}

pub fn main() -> Result<()> {
    let args = Args::parse();

    tracing_subscriber::fmt()
        .with_writer(std::io::stderr)
        .with_env_filter(
            tracing_subscriber::EnvFilter::from_default_env()
                .add_directive(tracing::Level::INFO.into()),
        )
        .init();

    tracing::info!("Loading sqlite DB and commit2vuln...");
    let mut commit2vuln = Commit2Vuln::new(&args.db, &args.commit2vuln)?;
    if let Some(subgraphwccs) = args.subgraphwccs {
        commit2vuln.with_subgraphwccs(&subgraphwccs)?;
    }

    tracing::info!("Loading graph...");
    let graph = SwhUnidirectionalGraph::new(&args.graph)
        .with_context(|| format!("Could not load graph from {}", args.graph.display()))?
        .init_properties()
        .load_properties(|properties| properties.load_maps::<DynMphf>())
        .context("Could not load maps")?;

    tracing::info!("Reading input...");

    let swhids = std::io::stdin().lines().filter_map(|line| {
        let line = line.ok()?;
        if line.is_empty() {
            None
        } else {
            Some(line.parse().context("Invalid SWHID"))
        }
    });

    let mut writer = csv::Writer::from_writer(std::io::stdout());
    swh_osv::commit2vuln::write_vulnerabilities_for_swhids(
        &mut commit2vuln,
        &graph,
        swhids,
        &mut writer,
    )?;

    tracing::info!("Done.");

    Ok(())
}
