use std::path::PathBuf;

use clap::Args;
use obikindex::KmerIndex;
use obilayeredmap::IndexMode;
use obisys::Reporter;
use tracing::info;

use crate::cli::block_size_to_bits;
use super::index::resolve_approx_params;

#[derive(Args)]
pub struct ReindexArgs {
    /// Index directory to convert (modified in-place)
    pub index: PathBuf,

    /// Convert to approximate evidence (default: convert to exact).
    /// Requires --evidence-bits and/or -z and/or --fp.
    #[arg(long, default_value_t = false)]
    pub approx: bool,

    /// Findere z parameter (≥1).
    #[arg(short = 'z', long, default_value = None)]
    pub findere_z: Option<u8>,

    /// Fingerprint bits per slot (b).
    #[arg(long, default_value = None)]
    pub evidence_bits: Option<u8>,

    /// Target false-positive rate per z-window.
    #[arg(long, default_value = None)]
    pub fp: Option<f64>,

    /// Block size for exact evidence `.idx` (number of unitigs per block).
    /// Ignored when converting to approximate evidence.
    #[arg(long, default_value_t = 1)]
    pub block_size: usize,
}

pub fn run(args: ReindexArgs) {
    let target = if args.approx {
        let (z, b, fp) = resolve_approx_params(args.findere_z, args.evidence_bits, args.fp);
        info!("target: approximate evidence — b={b}, z={z}, fp={fp:.2e}");
        IndexMode::Approx { b, z }
    } else {
        info!("target: exact evidence");
        IndexMode::Exact
    };

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

    info!(
        "current evidence: {:?}",
        idx.meta().config.evidence,
    );

    let block_bits = block_size_to_bits(args.block_size);
    let mut rep = Reporter::new();
    idx.reindex(target, block_bits, &mut rep).unwrap_or_else(|e| {
        eprintln!("reindex error: {e}");
        std::process::exit(1);
    });

    rep.print();
}
