//! Validate KVM differential snapshots: capture a base, change guest state,
//! snapshot_diff vs the base (storing only changed pages), then restore from the
//! diff and confirm the change is present — and that the diff file is far
//! smaller than a full snapshot.

#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
fn main() {
    use std::time::Duration;
    use supermachine::{Image, VmConfig};

    let base_dir = "/tmp/sm-diff-base";
    let diff_dir = "/tmp/sm-diff-delta";
    let _ = std::fs::remove_dir_all(base_dir);
    let _ = std::fs::remove_dir_all(diff_dir);

    let image = Image::from_oci("alpine").expect("from_oci");

    eprintln!("=== capture BASE snapshot ===");
    let vm0 = image.start(&VmConfig::new()).expect("start0");
    std::thread::sleep(Duration::from_millis(5000));
    let base = vm0.snapshot(base_dir).expect("base snapshot");
    let base_sz = std::fs::metadata(format!("{base_dir}/vm.snap"))
        .map(|m| m.len())
        .unwrap_or(0);
    eprintln!("base vm.snap = {} MiB", base_sz / (1024 * 1024));

    eprintln!("=== restore base, write a marker, capture DIFF ===");
    let vm1 = base.start(&VmConfig::new()).expect("start1");
    std::thread::sleep(Duration::from_millis(3000));
    let w = vm1
        .exec_builder()
        .argv([
            "/bin/sh",
            "-c",
            "echo diff-marker-9f3a > /root/marker && sync && cat /root/marker",
        ])
        .output()
        .expect("exec write");
    eprintln!(
        "wrote marker: success={} out={:?}",
        w.success(),
        String::from_utf8_lossy(&w.stdout).trim_end()
    );
    let diff = vm1.snapshot_diff(diff_dir, &base).expect("snapshot_diff");
    let diff_sz = std::fs::metadata(format!("{diff_dir}/vm.snap"))
        .map(|m| m.len())
        .unwrap_or(0);
    eprintln!(
        "diff vm.snap = {} MiB ({} KiB) — {:.1}% of base",
        diff_sz / (1024 * 1024),
        diff_sz / 1024,
        100.0 * diff_sz as f64 / base_sz.max(1) as f64
    );

    eprintln!("=== restore from DIFF, read the marker back ===");
    let vm2 = diff.start(&VmConfig::new()).expect("start2");
    std::thread::sleep(Duration::from_millis(3000));
    let r = vm2
        .exec_builder()
        .argv(["/bin/cat", "/root/marker"])
        .output()
        .expect("exec read");
    let got = String::from_utf8_lossy(&r.stdout).trim_end().to_string();
    eprintln!("diff-restore read: success={} out={:?}", r.success(), got);
    vm2.stop().ok();

    let pass = got == "diff-marker-9f3a" && diff_sz > 0 && diff_sz < base_sz;
    eprintln!(
        "=== SNAPSHOT_DIFF: {} ===",
        if pass { "PASS" } else { "FAIL" }
    );
}

#[cfg(not(all(target_os = "linux", target_arch = "x86_64")))]
fn main() {
    eprintln!("kvm_snapshot_diff is Linux/x86_64 only");
}
