vex-cli 0.7.13

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

use crate::daemon_client;

pub fn detect_pr(project: &str, ws_name: &str, host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();
    let mut params = json!({"project": project, "name": ws_name});
    if let Some(h) = host {
        params["host"] = json!(h);
    }
    match client.request("gh.detect-pr", params) {
        Ok(result) => {
            let linked = result
                .get("linked")
                .and_then(|v| v.as_bool())
                .unwrap_or(false);
            if linked {
                let number = result
                    .get("pr_number")
                    .and_then(|v| v.as_u64())
                    .unwrap_or(0);
                let url = result.get("pr_url").and_then(|v| v.as_str()).unwrap_or("-");
                println!("Linked PR #{number}: {url}");
            } else {
                println!("No PR found for this workstream's branch.");
            }
        }
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

pub fn link_pr(project: &str, ws_name: &str, pr_number: u64, host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();
    let mut params = json!({"project": project, "name": ws_name, "pr_number": pr_number});
    if let Some(h) = host {
        params["host"] = json!(h);
    }
    match client.request("gh.link-pr", params) {
        Ok(_) => println!("Linked PR #{pr_number}"),
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

pub fn unlink_pr(project: &str, ws_name: &str, host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();
    let mut params = json!({"project": project, "name": ws_name});
    if let Some(h) = host {
        params["host"] = json!(h);
    }
    match client.request("gh.unlink-pr", params) {
        Ok(_) => println!("Unlinked PR"),
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

pub fn link_issue(project: &str, ws_name: &str, issue_number: u64, host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();
    let mut params = json!({"project": project, "name": ws_name, "issue_number": issue_number});
    if let Some(h) = host {
        params["host"] = json!(h);
    }
    match client.request("gh.link-issue", params) {
        Ok(_) => println!("Linked issue #{issue_number}"),
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

pub fn unlink_issue(project: &str, ws_name: &str, issue_number: u64, host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();
    let mut params = json!({"project": project, "name": ws_name, "issue_number": issue_number});
    if let Some(h) = host {
        params["host"] = json!(h);
    }
    match client.request("gh.unlink-issue", params) {
        Ok(_) => println!("Unlinked issue #{issue_number}"),
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}

pub fn status(project: &str, ws_name: &str, host: Option<&str>) {
    let mut client = daemon_client::connect_to_hub_or_exit();
    let mut params = json!({"project": project, "name": ws_name});
    if let Some(h) = host {
        params["host"] = json!(h);
    }
    match client.request("gh.status", params) {
        Ok(result) => {
            if let Some(pr) = result.get("linked_pr").and_then(|v| v.as_object()) {
                let number = pr.get("number").and_then(|v| v.as_u64()).unwrap_or(0);
                let url = pr.get("url").and_then(|v| v.as_str()).unwrap_or("-");
                println!("PR: #{number} {url}");
            } else {
                println!("PR: (none)");
            }
            if let Some(issues) = result.get("linked_issues").and_then(|v| v.as_array()) {
                if issues.is_empty() {
                    println!("Issues: (none)");
                } else {
                    println!("Issues:");
                    for issue in issues {
                        let number = issue.get("number").and_then(|v| v.as_u64()).unwrap_or(0);
                        let url = issue.get("url").and_then(|v| v.as_str()).unwrap_or("-");
                        println!("  #{number} {url}");
                    }
                }
            }
        }
        Err(e) => {
            eprintln!("Error: {e}");
            std::process::exit(1);
        }
    }
}