//! `cargo xtask` — build automation (`ARCHITECTURE.md` §8.1), replacing ad-hoc
//! shell scripts. Run via the `xtask` alias in `.cargo/config.toml`.

use std::process::{Command, ExitCode};

/// Run a program, echoing the command, and report whether it succeeded.
fn run(program: &str, args: &[&str]) -> bool {
    eprintln!("$ {program} {}", args.join(" "));
    match Command::new(program).args(args).status() {
        Ok(status) => status.success(),
        Err(err) => {
            eprintln!("failed to spawn `{program}`: {err}");
            false
        }
    }
}

/// fmt + clippy + build + test across the workspace.
fn test_all() -> bool {
    run("cargo", &["fmt", "--all", "--check"])
        && run("cargo", &["clippy", "--workspace", "--all-targets"])
        && run("cargo", &["build", "--workspace"])
        && run("cargo", &["test", "--workspace"])
}

/// cargo-deny + cargo-audit.
fn audit() -> bool {
    let deny = run("cargo", &["deny", "check"]);
    let audit = run("cargo", &["audit"]);
    deny && audit
}

const USAGE: &str = "usage: cargo xtask <test-all|interop|coverage|audit|release>";

fn main() -> ExitCode {
    let task = std::env::args().nth(1);
    let ok = match task.as_deref() {
        Some("test-all") => test_all(),
        Some("audit") => audit(),
        Some("coverage") => {
            eprintln!(
                "xtask coverage: install cargo-llvm-cov, then `cargo llvm-cov --workspace` (§8.1)"
            );
            true
        }
        Some("interop") => {
            eprintln!(
                "xtask interop: requires a Python RNS reference; lands in Phase 1 (§7.4, §11.1)"
            );
            true
        }
        Some("release") => {
            eprintln!("xtask release: version bump + changelog + dry-run publish (Phase 4+, §8.1)");
            true
        }
        Some(other) => {
            eprintln!("unknown task: {other}\n{USAGE}");
            false
        }
        None => {
            eprintln!("{USAGE}");
            false
        }
    };

    if ok {
        ExitCode::SUCCESS
    } else {
        ExitCode::FAILURE
    }
}
