vex-cli 0.7.13

AI-native version control workflow engine
use serde_json::json;

use crate::daemon_client;

pub fn add(path: &str, host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();

    // Resolve to absolute path before sending to daemon
    let abs_path = match std::path::Path::new(path).canonicalize() {
        Ok(p) => p.to_string_lossy().to_string(),
        Err(_) => path.to_string(),
    };

    let mut params = json!({"path": abs_path});
    if let Some(h) = host {
        params["host"] = json!(h);
    }

    match client.request("project.add", params) {
        Ok(result) => {
            let name = result.get("name").and_then(|v| v.as_str()).unwrap_or("-");
            let path = result.get("path").and_then(|v| v.as_str()).unwrap_or("-");
            println!("Registered project '{name}' at {path}");
        }
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

pub fn list(host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();

    let mut params = json!({});
    if let Some(h) = host {
        params["host"] = json!(h);
    }

    match client.request("project.list", params) {
        Ok(result) => {
            let projects = result.as_array().cloned().unwrap_or_default();
            if projects.is_empty() {
                println!("No projects registered. Use 'vex project add <path>' to add one.");
                return;
            }
            println!("{:<12} {:<20} {:<40} REMOTE", "HOST", "NAME", "PATH");
            println!("{}", "".repeat(90));
            for p in &projects {
                println!(
                    "{:<12} {:<20} {:<40} {}",
                    p.get("host").and_then(|v| v.as_str()).unwrap_or("-"),
                    p.get("name").and_then(|v| v.as_str()).unwrap_or("-"),
                    p.get("path").and_then(|v| v.as_str()).unwrap_or("-"),
                    p.get("remote").and_then(|v| v.as_str()).unwrap_or("-"),
                );
            }
        }
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

pub fn remove(name: &str, host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();

    let mut params = json!({"name": name});
    if let Some(h) = host {
        params["host"] = json!(h);
    }

    match client.request("project.remove", params) {
        Ok(_) => println!("Removed project '{name}'"),
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}