//! Tauri commands for repository lifecycle (create, open, close).

use crate::state::AppState;
use brittle_core::Brittle;
use std::path::{Path, PathBuf};
use tauri::State;

/// Persist `path` as the last-opened project in the global config.
///
/// Best-effort: errors are logged to stderr rather than propagated, so they
/// never cause the primary open/create operation to fail.
fn save_last_opened(path: &Path) {
    match crate::config::GlobalConfig::load() {
        Ok(mut cfg) => {
            let path = path.to_owned();
            cfg.projects.recent.retain(|p| p != &path);
            cfg.projects.recent.insert(0, path.clone());
            cfg.projects.recent.truncate(10);
            cfg.projects.last_opened = Some(path);
            if let Err(e) = cfg.save() {
                eprintln!("[brittle] could not save config after open: {e}");
            }
        }
        Err(e) => eprintln!("[brittle] could not load config: {e}"),
    }
}

fn expand_tilde(path: &str) -> PathBuf {
    if let Some(rest) = path.strip_prefix("~/") {
        if let Ok(home) = std::env::var("HOME") {
            return PathBuf::from(home).join(rest);
        }
    }
    if path == "~" {
        if let Ok(home) = std::env::var("HOME") {
            return PathBuf::from(home);
        }
    }
    PathBuf::from(path)
}

/// Create a new Brittle repository at `path` and open it.
#[tauri::command]
pub fn create_repository(state: State<AppState>, path: String) -> Result<(), String> {
    let path = expand_tilde(&path);
    let brittle = Brittle::create(&path).map_err(|e| e.to_string())?;
    *state
        .brittle
        .lock()
        .map_err(|_| "lock poisoned".to_string())? = Some(brittle);
    save_last_opened(&path);
    Ok(())
}

/// Open an existing Brittle repository at `path`.
#[tauri::command]
pub fn open_repository(state: State<AppState>, path: String) -> Result<(), String> {
    let path = expand_tilde(&path);
    let brittle = Brittle::open(&path).map_err(|e| e.to_string())?;
    *state
        .brittle
        .lock()
        .map_err(|_| "lock poisoned".to_string())? = Some(brittle);
    save_last_opened(&path);
    Ok(())
}

/// Close the currently open repository. No-op if none is open.
#[tauri::command]
pub fn close_repository(state: State<AppState>) -> Result<(), String> {
    *state
        .brittle
        .lock()
        .map_err(|_| "lock poisoned".to_string())? = None;
    Ok(())
}

/// Return the filesystem path of the currently open repository.
#[tauri::command]
pub fn repository_root(state: State<AppState>) -> Result<String, String> {
    state.with_repo_read(|b| Ok(b.repository_root().to_string_lossy().into_owned()))
}
