use std::fs;
use std::path::PathBuf;
use chrono::{DateTime, Local};
use crate::collect::Snapshot;
pub fn dir() -> Option<PathBuf> {
dirs::data_local_dir().map(|d| d.join("syswatch").join("snapshots"))
}
pub fn write(snap: &Snapshot) -> anyhow::Result<PathBuf> {
let dir = dir().ok_or_else(|| anyhow::anyhow!("cannot determine local data directory"))?;
fs::create_dir_all(&dir)?;
let ts: DateTime<Local> = snap.t.into();
let stem = ts.format("snap-%Y-%m-%dT%H-%M-%S");
let path = dir.join(format!("{}.json", stem));
let body = serde_json::to_string_pretty(snap)?;
fs::write(&path, body)?;
Ok(path)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn dir_resolves_under_local_data() {
let Some(d) = dir() else { return };
let s = d.to_string_lossy();
assert!(s.contains("syswatch"));
assert!(s.ends_with("snapshots"));
}
#[test]
fn writes_snapshot_round_trips() {
let snap = Snapshot {
t: std::time::UNIX_EPOCH + std::time::Duration::from_secs(1_700_000_000),
host: Default::default(),
cpu: Default::default(),
mem: Default::default(),
disks: Vec::new(),
disk_io: Default::default(),
net: Vec::new(),
procs: Vec::new(),
gpus: Vec::new(),
power: Default::default(),
services: Vec::new(),
};
let body = serde_json::to_string_pretty(&snap).expect("serialize");
let v: serde_json::Value = serde_json::from_str(&body).expect("re-parse");
assert!(v.get("host").is_some());
assert!(v.get("cpu").is_some());
assert!(v.get("procs").is_some());
}
}