//! Criterion bench: blast-radius depth=3 across 100 / 1k / 10k symbols.
//!
//! Run with `cargo bench -p ckg-storage`. Reports land in
//! `target/criterion/blast-radius/` (HTML).

use ckg_core::{Edge, EdgeKind, Kind, RepoId, Symbol};
use ckg_storage::{Storage, queries};
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
use tempfile::tempdir;

fn make_symbol(i: usize) -> Symbol {
    Symbol {
        id: format!("s{i:06}"),
        qname: format!("crate::sym{i:06}"),
        name: format!("sym{i:06}"),
        kind: Kind::Function,
        file: "synthetic.rs".into(),
        line: i as u32 + 1,
        col: 0,
        is_public: true,
        doc: String::new(),
        hash: format!("h{i:06}"),
    }
}

fn build_storage(n: usize) -> (tempfile::TempDir, Storage) {
    let dir = tempdir().unwrap();
    // Benc-prefix is non-hex; use blake3 of the bench label so each
    // bench iteration gets a stable valid 24-hex RepoId.
    let id_src = format!("bench-blast-radius-{n}");
    let id = RepoId::try_new(blake3::hash(id_src.as_bytes()).to_hex()[..24].to_string()).unwrap();
    let st = Storage::open_unverified(id, dir.path()).unwrap();
    let symbols: Vec<Symbol> = (0..n).map(make_symbol).collect();
    st.put_symbols(&symbols).unwrap();
    let mut edges = Vec::with_capacity(n * 3);
    for i in 0..n {
        for j in 1..=3 {
            let dst = (i + j * 17 + 7) % n;
            edges.push(Edge {
                kind: EdgeKind::Calls,
                src: format!("s{i:06}"),
                dst: format!("s{dst:06}"),
                confidence: 1.0,
            });
        }
    }
    st.put_edges(&edges).unwrap();
    (dir, st)
}

fn bench(c: &mut Criterion) {
    let mut g = c.benchmark_group("blast-radius");
    for n in [100usize, 1_000, 10_000] {
        let (_dir, st) = build_storage(n);
        let seed = format!("s{:06}", n / 2);
        let (script, params) = queries::blast_radius(&seed, 3);
        g.bench_with_input(
            BenchmarkId::from_parameter(n),
            &(script, params),
            |b, (s, p)| {
                b.iter(|| st.run_with_immutable(s, p.clone()).unwrap());
            },
        );
    }
    g.finish();
}

criterion_group!(benches, bench);
criterion_main!(benches);
