//! Hot-write Ghostty theme from colors.toml (Darwin + NixOS).
//!
//! Uses a Ghostty *theme file* (`themes/dendritic-wallpaper`), not `config-file`.
//! macOS loads both XDG and Application Support configs (often the same file
//! via symlink); a `config-file` include then reports "cycle detected".

use std::path::{Path, PathBuf};
use std::process::Command;

use crate::palette::load_palette;
use crate::state;

fn theme_path() -> PathBuf {
    if let Ok(p) = std::env::var("DENDRITIC_GHOSTTY_LIVE") {
        return PathBuf::from(p);
    }
    state::home_dir()
        .map(|h| h.join(".config/ghostty/themes/dendritic-wallpaper"))
        .unwrap_or_else(|| PathBuf::from("dendritic-wallpaper"))
}

fn req<'a>(map: &'a std::collections::HashMap<String, String>, key: &str) -> Result<&'a str, String> {
    map.get(key)
        .map(String::as_str)
        .ok_or_else(|| format!("palette missing {key}"))
}

/// Write `~/.config/ghostty/themes/dendritic-wallpaper` from colors.toml.
pub fn write_live_from_colors(colors_path: &Path) -> Result<PathBuf, String> {
    let p = load_palette(colors_path)?;
    let b00 = req(&p, "base00")?;
    let b02 = req(&p, "base02")?;
    let b03 = req(&p, "base03")?;
    let b05 = req(&p, "base05")?;
    let b07 = req(&p, "base07")?;
    let b08 = req(&p, "base08")?;
    let b0a = req(&p, "base0A")?;
    let b0b = req(&p, "base0B")?;
    let b0c = req(&p, "base0C")?;
    let b0d = req(&p, "base0D")?;
    let b0e = req(&p, "base0E")?;

    // Theme files use hex without '#' for some keys; palette entries keep '#'.
    let strip = |h: &str| -> String { h.trim().trim_start_matches('#').to_string() };
    let b00 = strip(b00);
    let b02 = strip(b02);
    let b03 = strip(b03);
    let b05 = strip(b05);
    let b07 = strip(b07);
    let b08 = strip(b08);
    let b0a = strip(b0a);
    let b0b = strip(b0b);
    let b0c = strip(b0c);
    let b0d = strip(b0d);
    let b0e = strip(b0e);
    let body = format!(
        r##"# Generated by dendritic-appearance from ~/.colors.toml — do not edit.
# Wallpaper-derived base16 theme (HM sets theme = dendritic-wallpaper).
background = {b00}
foreground = {b05}
cursor-color = {b05}
selection-background = {b02}
selection-foreground = {b05}
palette = 0=#{b00}
palette = 1=#{b08}
palette = 2=#{b0b}
palette = 3=#{b0a}
palette = 4=#{b0d}
palette = 5=#{b0e}
palette = 6=#{b0c}
palette = 7=#{b05}
palette = 8=#{b03}
palette = 9=#{b08}
palette = 10=#{b0b}
palette = 11=#{b0a}
palette = 12=#{b0d}
palette = 13=#{b0e}
palette = 14=#{b0c}
palette = 15=#{b07}
"##
    );

    let dest = theme_path();
    if let Some(parent) = dest.parent() {
        std::fs::create_dir_all(parent).map_err(|e| format!("mkdir {}: {e}", parent.display()))?;
    }
    // Replace HM store symlink if present (same pattern as ~/.colors.toml).
    let _ = std::fs::remove_file(&dest);
    std::fs::write(&dest, body).map_err(|e| format!("write {}: {e}", dest.display()))?;
    #[cfg(unix)]
    {
        use std::os::unix::fs::PermissionsExt;
        let _ = std::fs::set_permissions(&dest, std::fs::Permissions::from_mode(0o644));
    }
    Ok(dest)
}

pub fn reload() {
    // Ghostty (macOS app + Linux) reloads config on SIGUSR2.
    let _ = Command::new("pkill")
        .args(["-USR2", "-x", "Ghostty"])
        .status();
    let _ = Command::new("pkill")
        .args(["-USR2", "-x", "ghostty"])
        .status();
}

pub fn apply_from_colors(colors_path: &Path) -> Result<(), String> {
    let _ = write_live_from_colors(colors_path)?;
    reload();
    Ok(())
}
