pub mod app;
pub mod config;
pub mod generate;
pub mod registry;

pub use config::{
    CommandSequence, KeyBinding, OptionEntry, PluginEntry, TmuxConfig, Workspace, WorkspacePane,
    WorkspaceSession, WorkspaceWindow,
};
pub use generate::generate_conf;

use anyhow::{Context, Result};
use std::fs;
use std::path::PathBuf;
use std::process::Command;

impl TmuxConfig {
    pub fn apply(&self) -> Result<()> {
        let conf_path = default_tmux_conf_path()?;
        let content = generate_conf(self);
        fs::write(&conf_path, &content).context("Failed to write .tmux.conf")?;

        if Command::new("tmux").arg("-V").output().is_err() {
            return Ok(());
        }

        let status = Command::new("tmux")
            .args(["source-file", conf_path.to_str().unwrap_or("~/.tmux.conf")])
            .status()
            .context("Failed to run tmux source-file")?;

        if status.success() {
            Ok(())
        } else {
            Err(anyhow::anyhow!(
                "tmux source-file failed (is a server running?)"
            ))
        }
    }

    pub fn spawn_workspace(&self, ws: &Workspace) -> Result<()> {
        if ws.sessions.is_empty() {
            return Err(anyhow::anyhow!("Workspace '{}' has no sessions", ws.name));
        }

        if Command::new("tmux").arg("-V").output().is_err() {
            return Err(anyhow::anyhow!("tmux not found on PATH"));
        }

        let script = generate::generate_workspace_script(ws);
        let tmp = std::env::temp_dir().join("tumix_spawn.sh");
        fs::write(&tmp, script).context("Failed to write spawn script")?;

        let status = if cfg!(windows) {
            Command::new("sh")
                .arg(tmp.to_str().unwrap())
                .status()
                .context("Failed to run spawn script (needs sh/WSL)")?
        } else {
            Command::new("sh")
                .arg(tmp.to_str().unwrap())
                .status()
                .context("Failed to run spawn script")?
        };

        if !status.success() {
            anyhow::bail!("Spawn script failed");
        }
        Ok(())
    }
}

pub fn default_tmux_conf_path() -> Result<PathBuf> {
    let home = std::env::var("HOME")
        .or_else(|_| std::env::var("USERPROFILE"))
        .context("Could not find home directory")?;
    Ok(PathBuf::from(home).join(".tmux.conf"))
}

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

    #[test]
    fn generates_valid_prefix() {
        let mut config = TmuxConfig::default();
        config.set_option("prefix".into(), "C-a".into());
        let conf = generate_conf(&config);
        assert!(conf.contains("set -g prefix C-a"));
        assert!(conf.contains("unbind C-b"));
    }
}
