//! Time the one-shot path: from API call to VM-running-and-result-returned,
//! producing a reusable snapshot as a side effect (current API). Equivalent
//! comparison point against libkrun cold-boot.
//!
//! Reports per-phase timings exposed via the snapshot's metadata.json.

use std::time::Instant;
use supermachine::Image;

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let home = std::env::var("HOME")?;
    let name = std::env::var("ONE_SHOT_NAME").unwrap_or_else(|_| "_one_shot_timing".to_string());
    let snap_dir = format!("{home}/.local/supermachine-snapshots/{name}");

    // Clean previous snapshot if user asked.
    if std::env::var("ONE_SHOT_CLEAN").ok().as_deref() == Some("1") {
        let _ = std::fs::remove_dir_all(&snap_dir);
    }

    let total_t0 = Instant::now();
    let mut b = Image::builder("rust:1-slim").with_name(&name);
    if std::env::var("ONE_SHOT_NEVER_PULL").ok().as_deref() == Some("1") {
        b = b.with_pull_policy(supermachine::PullPolicy::Never);
    }
    let image = b.build()?;
    let bake_ms = total_t0.elapsed().as_millis();
    eprintln!("[oneshot] Image::builder().build(): {} ms", bake_ms);

    // Per-phase from metadata.json
    let meta_path = format!("{snap_dir}/metadata.json");
    if let Ok(s) = std::fs::read_to_string(&meta_path) {
        if let Ok(v) = serde_json::from_str::<serde_json::Value>(&s) {
            if let Some(t) = v.get("timings") {
                eprintln!("[oneshot] phases:");
                let print_key = |k: &str| {
                    if let Some(val) = t.get(k) {
                        eprintln!("  {}: {}", k, val);
                    }
                };
                for k in [
                    "pull_inspect_ms",
                    "rootfs_prepare_ms",
                    "rootfs_customize_ms",
                    "squashfs_ms",
                    "initramfs_ms",
                    "vmm_bake_ms",
                    "metadata_prepare_ms",
                    "guest_boot_to_listener_ms",
                    "snapshot_capture_us",
                    "snapshot_save_us",
                    "total_ms",
                ] {
                    print_key(k);
                }
            }
        }
    }

    // First exec (acquire from snapshot + run /bin/true + return)
    let pool = image.pool().min(0).max(1).build()?;
    let acquire_t0 = Instant::now();
    let vm = pool.acquire()?;
    let acquire_ms = acquire_t0.elapsed().as_millis();
    eprintln!(
        "[oneshot] pool.build() done; acquire took {} ms",
        acquire_ms
    );

    let exec_t0 = Instant::now();
    let _ = vm
        .exec_builder()
        .argv(["true"])
        .timeout(std::time::Duration::from_secs(10))
        .output()?;
    let exec_ms = exec_t0.elapsed().as_millis();
    eprintln!("[oneshot] exec /bin/true: {} ms", exec_ms);
    eprintln!(
        "[oneshot] TOTAL (Image::build + acquire + exec): {} ms",
        total_t0.elapsed().as_millis()
    );

    Ok(())
}
