import { Hono } from "hono";
import { resolveBinaryAsync, getEnrichedPath } from "../path-resolver.js";
import { createLogger } from "../logger.js";

const log = createLogger("prerequisites-routes");

/** Binary version check timeout (ms). */
const VERSION_TIMEOUT_MS = 3_000;

interface PrerequisiteStatus {
  installed: boolean;
  version: string | null;
  required: boolean;
  description: string;
  installCommand: string | null;
  installUrl: string | null;
}

interface PrerequisitesResponse {
  bun: PrerequisiteStatus;
  claude: PrerequisiteStatus;
  codex: PrerequisiteStatus;
  docker: PrerequisiteStatus;
  git: PrerequisiteStatus;
  /** True if at least one CLI backend (claude or codex) is available. */
  hasRequiredCli: boolean;
}

/**
 * Spawn a binary with `--version` and capture the version string.
 * Returns null if the binary is not found or the command times out.
 */
async function getBinaryVersion(binary: string, versionArg = "--version"): Promise<string | null> {
  try {
    const proc = Bun.spawn([binary, versionArg], {
      stdout: "pipe",
      stderr: "pipe",
      env: { ...process.env, PATH: getEnrichedPath() },
    });

    const timeout = setTimeout(() => proc.kill(), VERSION_TIMEOUT_MS);
    const exitCode = await proc.exited;
    clearTimeout(timeout);

    if (exitCode !== 0) return null;

    const stdout = (await new Response(proc.stdout).text()).trim();
    // Extract version number from output like "1.2.3" or "claude v1.2.3" or "git version 2.39.0"
    const versionMatch = stdout.match(/(\d+\.\d+(?:\.\d+)?(?:[.\-+a-zA-Z0-9]*)?)/);
    return versionMatch?.[1] ?? stdout.split("\n")[0]?.trim() ?? null;
  } catch {
    return null;
  }
}

/**
 * Creates unauthenticated prerequisite-check routes.
 * Mounted BEFORE the auth middleware so the setup wizard can
 * check prerequisites without requiring a token.
 */
export function createPrerequisitesRoutes(): Hono {
  const app = new Hono();

  app.get("/prerequisites", async (c) => {
    // Run all binary checks in parallel for speed
    const [
      claudePath,
      codexPath,
      dockerPath,
      gitPath,
    ] = await Promise.all([
      resolveBinaryAsync("claude"),
      resolveBinaryAsync("codex"),
      resolveBinaryAsync("docker"),
      resolveBinaryAsync("git"),
    ]);

    // Only fetch versions for binaries that exist (Bun.which is fast, --version is slow)
    const [
      claudeVersion,
      codexVersion,
      dockerVersion,
      gitVersion,
    ] = await Promise.all([
      claudePath ? getBinaryVersion(claudePath) : Promise.resolve(null),
      codexPath ? getBinaryVersion(codexPath) : Promise.resolve(null),
      dockerPath ? getBinaryVersion(dockerPath) : Promise.resolve(null),
      gitPath ? getBinaryVersion(gitPath) : Promise.resolve(null),
    ]);

    // Bun is always installed since the server is running
    const bunVersion = typeof Bun !== "undefined" ? Bun.version : null;

    const response: PrerequisitesResponse = {
      bun: {
        installed: true,
        version: bunVersion,
        required: false,
        description: "JavaScript runtime (server is running)",
        installCommand: null,
        installUrl: "https://bun.sh",
      },
      claude: {
        installed: !!claudePath,
        version: claudeVersion,
        required: true,
        description: "Claude Code CLI for AI-assisted development",
        installCommand: "npm install -g @anthropic-ai/claude-code",
        installUrl: "https://docs.anthropic.com/en/docs/claude-code",
      },
      codex: {
        installed: !!codexPath,
        version: codexVersion,
        required: false,
        description: "OpenAI Codex CLI (alternative backend)",
        installCommand: "npm install -g @openai/codex",
        installUrl: "https://github.com/openai/codex",
      },
      docker: {
        installed: !!dockerPath,
        version: dockerVersion,
        required: false,
        description: "Container runtime for isolated sessions",
        installCommand: null,
        installUrl: "https://docs.docker.com/get-docker/",
      },
      git: {
        installed: !!gitPath,
        version: gitVersion,
        required: false,
        description: "Version control for branch & worktree features",
        installCommand: null,
        installUrl: "https://git-scm.com/downloads",
      },
      hasRequiredCli: !!claudePath || !!codexPath,
    };

    log.debug(
      {
        claude: !!claudePath,
        codex: !!codexPath,
        docker: !!dockerPath,
        git: !!gitPath,
      },
      "Prerequisites check completed",
    );

    return c.json(response);
  });

  return app;
}
