//! Host context probes. All best-effort: a probe that fails degrades to a
//! placeholder value and never fails a bench (the report stays honest via the
//! host block committed inside each baseline).

use crate::baseline::HostInfo;

pub fn host_info() -> HostInfo {
    let hostname = std::fs::read_to_string("/proc/sys/kernel/hostname")
        .map(|s| s.trim().to_string())
        .unwrap_or_else(|_| "unknown".to_string());
    let nproc = std::thread::available_parallelism().map(|n| n.get() as u32).unwrap_or(0);
    HostInfo { hostname, nproc }
}

/// 1-minute loadavg, or `None` when unreadable.
pub fn loadavg_1m() -> Option<f64> {
    let text = std::fs::read_to_string("/proc/loadavg").ok()?;
    text.split_whitespace().next()?.parse().ok()
}

/// Short commit of the enclosing worktree, best-effort.
pub fn git_commit() -> String {
    std::process::Command::new("git")
        .args(["rev-parse", "--short", "HEAD"])
        .output()
        .ok()
        .filter(|o| o.status.success())
        .map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
        .unwrap_or_else(|| "unknown".to_string())
}

/// UTC date `YYYY-MM-DD`, best-effort via `date -u`.
pub fn today() -> String {
    std::process::Command::new("date")
        .args(["-u", "+%F"])
        .output()
        .ok()
        .filter(|o| o.status.success())
        .map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
        .unwrap_or_else(|| "unknown".to_string())
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn host_info_reads_something() {
        let h = host_info();
        assert!(!h.hostname.is_empty());
    }

    /// #251: every committed baseline records `commit` for provenance (a
    /// baseline that can't be tied to the code it measured is useless for
    /// drift comparison). This test runs inside a real git worktree, so
    /// `git_commit` must shell out and parse successfully — falling silently
    /// back to `"unknown"` here would be exactly the failure mode the
    /// best-effort fallback exists to hide, and this pins the happy path
    /// rather than only the "never panics" degenerate case.
    #[test]
    fn git_commit_reports_the_real_short_hash_inside_a_git_worktree() {
        let commit = git_commit();
        assert_ne!(commit, "unknown", "must read the real worktree HEAD, not fall back silently");
        assert!(
            commit.len() >= 7 && commit.chars().all(|c| c.is_ascii_hexdigit()),
            "not a short hex hash: {commit:?}"
        );
    }
}
