//! Shared helpers for invoking the GitHub CLI (`gh`).
//!
//! Used by both `CloneHost` (cloning the platform monorepo) and the new
//! `sources_resolver` (cloning dependency apps). Keeping the auth/access
//! checks in one place ensures the same diagnostics in both call sites.

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

use anyhow::{bail, Result};

/// Return the absolute path to `bin` on `$PATH`, if any.
pub fn which(bin: &str) -> Option<PathBuf> {
    let path = std::env::var_os("PATH")?;
    for dir in std::env::split_paths(&path) {
        let candidate = dir.join(bin);
        if candidate.is_file() {
            return Some(candidate);
        }
    }
    None
}

/// Whether `gh auth status` returns success.
pub fn gh_auth_ok() -> bool {
    if which("gh").is_none() {
        return false;
    }
    Command::new("gh")
        .args(["auth", "status"])
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .status()
        .map(|s| s.success())
        .unwrap_or(false)
}

/// Verify `gh` is installed, authenticated, and that the caller has read
/// access to `repo` (e.g. `econ-v1/node`). Errors describe the missing step.
pub fn ensure_gh_auth_and_access(repo: &str) -> Result<()> {
    if which("gh").is_none() {
        bail!(
            "GitHub CLI (`gh`) not found on PATH.\n\
             Install from https://cli.github.com, then run `gh auth login`."
        );
    }
    if !gh_auth_ok() {
        bail!(
            "`gh auth status` failed — run `gh auth login` first.\n\
             (Cloning {repo} requires read access.)"
        );
    }
    let access = Command::new("gh")
        .args(["api", &format!("repos/{}", repo)])
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .status()
        .map(|s| s.success())
        .unwrap_or(false);
    if !access {
        bail!(
            "your GitHub account doesn't have read access to {repo}.\n\
             If you're an in-house contributor, ask the team to add you to the org."
        );
    }
    Ok(())
}
