//! Instance registry for running adom-video-post web UIs.
//!
//! Every `run_webapp` invocation writes a small JSON file to
//! `~/.adom/adom-video-post/instances/{pid}.json` on startup, and
//! deletes it on clean shutdown or on SIGTERM/SIGINT. The
//! `adom-video-post list` subcommand reads this directory (filtering
//! out stale entries whose pid is dead), and `adom-video-post ctrl`
//! resolves symbolic targets like `voiceover` / `storyboard` /
//! `latest` to a concrete port by scanning it.
//!
//! This module only implements the write/unregister side. The
//! list/ctrl side is in the top-level `ctrl` module (Phase 1.5).

use std::fs;
use std::path::PathBuf;

pub struct InstanceEntry {
    pub pid: u32,
    pub port: u16,
    pub subcommand: String,
    pub title: String,
}

/// Write a registry entry for the current process. Returns the
/// absolute path of the file that was written (so `unregister`
/// can later remove exactly that file).
pub fn register(entry: &InstanceEntry) -> Result<PathBuf, String> {
    let dir = instances_dir()?;
    fs::create_dir_all(&dir).map_err(|e| format!("mkdir {}: {}", dir.display(), e))?;
    let path = dir.join(format!("{}.json", entry.pid));
    let started_at = std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .map(|d| d.as_secs())
        .unwrap_or(0);
    let cwd = std::env::current_dir()
        .map(|p| p.display().to_string())
        .unwrap_or_default();
    let body = format!(
        r#"{{"pid":{},"port":{},"subcommand":{},"title":{},"startedAt":{},"cwd":{}}}"#,
        entry.pid,
        entry.port,
        serde_json::to_string(&entry.subcommand).unwrap(),
        serde_json::to_string(&entry.title).unwrap(),
        started_at,
        serde_json::to_string(&cwd).unwrap(),
    );
    fs::write(&path, body).map_err(|e| format!("write {}: {}", path.display(), e))?;
    Ok(path)
}

/// Remove a previously-written registry file. Silently ignores
/// "file not found" — the SIGTERM handler and normal shutdown
/// path both call this, and racing on the unlink is fine.
pub fn unregister(path: &std::path::Path) {
    let _ = fs::remove_file(path);
}

pub fn instances_dir() -> Result<PathBuf, String> {
    let home = std::env::var("HOME").map_err(|_| "HOME not set".to_string())?;
    Ok(PathBuf::from(home).join(".adom/adom-video-post/instances"))
}