/**
 * Provider scanner — detects which AI providers are available on this machine.
 *
 * Checks environment variables and CLI tool availability.
 */

import { execSync } from 'child_process';

export interface ProviderScanResult {
  id: string;
  available: boolean;
  hasApiKey: boolean;
  hasCli: boolean;
  cliPath: string | null;
  version: string | null;
}

function whichSync(bin: string): string | null {
  try {
    return execSync(`which ${bin}`, { encoding: 'utf8', timeout: 3000 }).trim() || null;
  } catch {
    return null;
  }
}

function getVersion(bin: string): string | null {
  try {
    const out = execSync(`${bin} --version`, { encoding: 'utf8', timeout: 5000 }).trim();
    // Extract first version-like string
    const match = out.match(/(\d+\.\d+[\w.-]*)/);
    return match ? match[1] : out.slice(0, 40);
  } catch {
    return null;
  }
}

export async function scanClaude(): Promise<ProviderScanResult> {
  const hasApiKey = !!process.env.ANTHROPIC_API_KEY;
  const cliPath = whichSync('claude');
  return {
    id: 'claude',
    available: hasApiKey || !!cliPath,
    hasApiKey,
    hasCli: !!cliPath,
    cliPath,
    version: cliPath ? getVersion('claude') : null,
  };
}

export async function scanCodex(): Promise<ProviderScanResult> {
  const hasApiKey = !!process.env.OPENAI_API_KEY;
  const cliPath = whichSync('codex');
  return {
    id: 'codex',
    available: hasApiKey || !!cliPath,
    hasApiKey,
    hasCli: !!cliPath,
    cliPath,
    version: cliPath ? getVersion('codex') : null,
  };
}

export async function scanOllama(): Promise<ProviderScanResult> {
  const cliPath = whichSync('ollama');
  let serverUp = false;
  try {
    const res = await fetch('http://localhost:11434/api/version', {
      signal: AbortSignal.timeout(2000),
    });
    serverUp = res.ok;
  } catch {
    // ECONNREFUSED or timeout — server not running
  }
  return {
    id: 'ollama',
    available: serverUp || !!cliPath,
    hasApiKey: false,
    hasCli: !!cliPath,
    cliPath,
    version: cliPath ? getVersion('ollama') : null,
  };
}

export async function scanGemini(): Promise<ProviderScanResult> {
  const hasApiKey = !!process.env.GEMINI_API_KEY;
  return {
    id: 'gemini',
    available: hasApiKey,
    hasApiKey,
    hasCli: false,
    cliPath: null,
    version: null,
  };
}

/**
 * Scan all known providers. Returns results for each.
 */
export async function scanAllProviders(): Promise<ProviderScanResult[]> {
  const [claude, codex, ollama, gemini] = await Promise.all([
    scanClaude(),
    scanCodex(),
    scanOllama(),
    scanGemini(),
  ]);
  return [claude, codex, ollama, gemini];
}
