/**
 * External-tool health checks. Surfaced two ways:
 *   - On startup (lib/init.ts) — one log line per tool with install hint
 *     if missing, so server logs make the problem obvious
 *   - Via `GET /api/health/tools` — the Pipelines view uses this to show
 *     a banner when a tool needed by a built-in workflow isn't installed
 *
 * Add new tools by extending CHECKS. Tools are marked "optional" when a
 * subset of Forge features needs them — the absence isn't an error, just
 * a heads-up that those features won't work.
 */

import { execSync } from 'node:child_process';

export interface ToolStatus {
  /** binary name as invoked from PATH */
  name: string;
  /** human-readable label for UI */
  label: string;
  /** what part of Forge needs this — shown in the warning */
  needed_for: string;
  /** absolute path if installed, '' otherwise */
  path: string;
  /** parsed version string if we could pull one */
  version: string;
  /** true iff `which <name>` found it */
  installed: boolean;
  /** copy-pasteable install / auth instructions when missing */
  install_hint: string;
}

interface Check {
  name: string;
  label: string;
  needed_for: string;
  versionFlag?: string;          // arg to invoke for version probe (default --version)
  install_hint: string;
}

const CHECKS: Check[] = [
  {
    name: 'glab',
    label: 'GitLab CLI',
    needed_for: 'gitlab-issue-fix-and-review + mantis-bug-fix-and-mr pipelines (push branches + open MRs)',
    install_hint: [
      'macOS:  brew install glab',
      'Linux:  https://gitlab.com/gitlab-org/cli/-/releases (deb/rpm/tar)',
      'Windows: winget install GitLab.cli',
      'Then auth once per host:  glab auth login --hostname <your-gitlab.example.com>',
    ].join('\n'),
  },
  {
    name: 'gh',
    label: 'GitHub CLI',
    needed_for: 'issue-fix-and-review pipeline + GitHub issue scanner',
    install_hint: [
      'macOS:  brew install gh',
      'Linux:  https://cli.github.com/manual/installation',
      'Then auth once:  gh auth login',
    ].join('\n'),
  },
  {
    name: 'git',
    label: 'git',
    needed_for: 'every pipeline (worktree, fetch, push)',
    install_hint: [
      'macOS:  xcode-select --install   (or brew install git)',
      'Linux:  apt install git  /  dnf install git',
      'Windows: https://git-scm.com/download/win',
    ].join('\n'),
  },
  {
    name: 'jq',
    label: 'jq',
    needed_for: 'gitlab-issue-fix-and-review (parses glab JSON)',
    install_hint: [
      'macOS:  brew install jq',
      'Linux:  apt install jq  /  dnf install jq',
    ].join('\n'),
  },
];

function which(bin: string): string {
  try {
    return execSync(`which ${bin}`, { encoding: 'utf-8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
  } catch {
    return '';
  }
}

function version(bin: string, flag = '--version'): string {
  try {
    const out = execSync(`${bin} ${flag}`, { encoding: 'utf-8', timeout: 3000, stdio: ['pipe', 'pipe', 'pipe'] }).trim();
    // First line, usually like "git version 2.42.0" or "glab version 1.40.0 (...)"
    return out.split('\n')[0] || '';
  } catch {
    return '';
  }
}

export function checkTools(): ToolStatus[] {
  return CHECKS.map((c) => {
    const path = which(c.name);
    return {
      name: c.name,
      label: c.label,
      needed_for: c.needed_for,
      path,
      version: path ? version(c.name, c.versionFlag) : '',
      installed: !!path,
      install_hint: c.install_hint,
    };
  });
}

/**
 * Log a one-line summary per tool to the startup console. For missing
 * ones, also log the install hint so users see it without poking at the
 * UI.
 */
export function logToolStatus(): void {
  const results = checkTools();
  for (const r of results) {
    if (r.installed) {
      console.log(`[tools] ✓ ${r.name.padEnd(6)} ${r.version || r.path}`);
    } else {
      console.warn(`[tools] ✗ ${r.name.padEnd(6)} NOT FOUND — ${r.needed_for}`);
      for (const line of r.install_hint.split('\n')) console.warn(`         ${line}`);
    }
  }
}
