import { execSync } from 'node:child_process';
import { platform } from 'node:os';
import type { RuntimeName } from '../types.js';

export interface RuntimeInfo {
  name: RuntimeName;
  label: string;
  installed: boolean;
  path?: string;
  version?: string;
  installHint: string;
}

const RUNTIME_DEFS: Record<
  RuntimeName,
  { label: string; command: string; versionFlag: string; installHint: string }
> = {
  claude: {
    label: 'Claude Code',
    command: 'claude',
    versionFlag: '--version',
    installHint: 'npm install -g @anthropic-ai/claude-code',
  },
  codex: {
    label: 'Codex',
    command: 'codex',
    versionFlag: '--version',
    installHint: 'npm install -g @openai/codex',
  },
  opencode: {
    label: 'OpenCode',
    command: 'opencode',
    versionFlag: 'version',
    installHint: 'See https://opencode.ai for install instructions',
  },
  pi: {
    label: 'Pi',
    command: 'pi',
    versionFlag: '--version',
    installHint: 'npm install -g @mariozechner/pi-coding-agent',
  },
};

export function detectRuntime(name: RuntimeName): RuntimeInfo {
  const def = RUNTIME_DEFS[name];
  const isWindows = platform() === 'win32';
  const whichCmd = isWindows ? `where ${def.command} 2>nul` : `which ${def.command} 2>/dev/null`;

  try {
    const pathOutput =
      execSync(whichCmd, {
        encoding: 'utf-8',
        timeout: 5000,
      })
        .trim()
        .split('\n')[0] ?? '';

    let version: string | undefined;
    try {
      version = execSync(`${def.command} ${def.versionFlag} 2>/dev/null`, {
        encoding: 'utf-8',
        timeout: 5000,
      }).trim();
    } catch {
      // Version detection is optional
    }

    return {
      name,
      label: def.label,
      installed: true,
      path: pathOutput,
      version,
      installHint: def.installHint,
    };
  } catch {
    return {
      name,
      label: def.label,
      installed: false,
      installHint: def.installHint,
    };
  }
}

export function getInstallInstructions(name: RuntimeName): string {
  return RUNTIME_DEFS[name].installHint;
}
