// Mimics ISO dump exactly — read + write + progress
use libfreemkv::Drive;
use std::io::Write;
use std::path::Path;
use std::time::Instant;

fn main() {
    let device = std::env::args()
        .skip(1)
        .find(|a| !a.starts_with('-'))
        .unwrap_or_else(|| match libfreemkv::find_drive() {
            Some(d) => d.device_path().to_string(),
            None => {
                eprintln!("No drives found");
                std::process::exit(1);
            }
        });

    let mut drive = Drive::open(Path::new(&device)).unwrap_or_else(|e| {
        eprintln!("Cannot open {}: {}", device, e);
        std::process::exit(1);
    });
    eprintln!("wait_ready...");
    let _ = drive.wait_ready();
    eprintln!("read_capacity...");
    let cap = drive.read_capacity().unwrap();
    eprintln!("capacity: {} sectors", cap);

    let batch = libfreemkv::disc::detect_max_batch_sectors(drive.device_path());
    let mut buf = vec![0u8; batch as usize * 2048];

    // Open /dev/null writer like ISO dump does
    let file = std::fs::File::create("/dev/null").unwrap();
    let mut writer = std::io::BufWriter::with_capacity(4 * 1024 * 1024, file);

    eprintln!(
        "Reading 1000 batches ({:.1} MB) with write + progress...",
        1000.0 * batch as f64 * 2048.0 / 1_048_576.0
    );

    let start = Instant::now();
    let mut ok = 0u32;
    let mut fail = 0u32;
    let mut bytes: u64 = 0;

    // Recovery flag: true matches pre-0.11.13 bench behavior — full SCSI
    // ECC retry loop on errors (slower, what the rip path used before the
    // adaptive batch sizer landed). Flip to `false` for the fast-fail path
    // that current rips use; benches are configurable via this constant.
    const READ_WITH_RECOVERY: bool = true;

    for i in 0..1000u32 {
        let lba = i * batch as u32;
        match drive.read(lba, batch, &mut buf, READ_WITH_RECOVERY) {
            Ok(_) => {
                writer.write_all(&buf).unwrap();
                ok += 1;
            }
            Err(e) => {
                fail += 1;
                if fail <= 5 {
                    eprintln!("  FAIL LBA {}: {}", lba, e);
                }
                buf.fill(0);
                writer.write_all(&buf).unwrap();
            }
        }
        bytes += buf.len() as u64;

        if i % 50 == 0 && i > 0 {
            let elapsed = start.elapsed().as_secs_f64();
            let mb = bytes as f64 / 1_048_576.0;
            eprint!("\r  {:.1} MB | {:.1} MB/s    ", mb, mb / elapsed);
        }
    }

    let elapsed = start.elapsed().as_secs_f64();
    let mb = ok as f64 * batch as f64 * 2048.0 / 1_048_576.0;
    eprintln!(
        "\n{} ok, {} fail, {:.1} MB in {:.1}s = {:.1} MB/s",
        ok,
        fail,
        mb,
        elapsed,
        mb / elapsed
    );
}
