use std::io::{self, BufWriter, Write};
use std::path::PathBuf;

use clap::Args;
use obidebruinj::GraphDeBruijn;
use obifastwrite::write_unitig;
use obikindex::KmerIndex;
use tracing::info;

use super::predicate::FilterArgs;

#[derive(Args)]
pub struct UnitigArgs {
    /// Index directory
    pub index: PathBuf,

    #[command(flatten)]
    pub filter: FilterArgs,
}

pub fn run(args: UnitigArgs) {
    let idx = KmerIndex::open(&args.index).unwrap_or_else(|e| {
        eprintln!("error opening index: {e}");
        std::process::exit(1);
    });

    let k          = idx.kmer_size();
    let n          = idx.n_partitions();
    let n_genomes  = idx.meta().genomes.len().max(1);
    let use_counts = idx.meta().config.with_counts;

    info!("unitig: building de Bruijn graph from {n} partition(s) (k={k})");

    let filters = args.filter.build_filters(&idx.meta().genomes);

    // ── Collect all filtered kmers into a single de Bruijn graph ─────────────
    let mut g = GraphDeBruijn::new();

    for i in 0..n {
        idx.partition()
            .iter_partition_kmers(i, use_counts, n_genomes, &filters, |kmer, _row| {
                g.push(kmer);
            })
            .unwrap_or_else(|e| {
                eprintln!("error reading partition {i}: {e}");
                std::process::exit(1);
            });
    }

    info!("unitig: {} distinct k-mers", g.len());
    g.compute_degrees();

    // ── Enumerate unitigs and write as FASTA ──────────────────────────────────
    let stdout = io::stdout();
    let mut out = BufWriter::new(stdout.lock());

    for (j, unitig) in g.iter_unitig().enumerate() {
        write_unitig(&unitig, k, 0, j, &mut out).unwrap_or_else(|e| {
            eprintln!("write error: {e}");
            std::process::exit(1);
        });
    }

    out.flush().expect("flush error");
}
