import * as p from "@clack/prompts";
import pc from "picocolors";
import { detectHardware, type HardwareTier } from "./hardware.js";
import { printBuildthisBanner } from "./banner.js";

/**
 * Probe whether a Nexus instance is running on the given port.
 * Returns true if the health endpoint responds with HTTP 200 within 2 seconds.
 */
export async function probeRunningInstance(port: number): Promise<boolean> {
  try {
    const res = await fetch(`http://127.0.0.1:${port}/api/health`, {
      signal: AbortSignal.timeout(2000),
    });
    return res.ok;
  } catch {
    return false;
  }
}

/**
 * Build the provider selection options based on hardware tier.
 * Excludes local AI for cpu_only machines (too slow for practical use).
 */
export function getProviderOptions(tier: HardwareTier): Array<{ value: string; label: string; hint: string }> {
  const options: Array<{ value: string; label: string; hint: string }> = [
    {
      value: "puter",
      label: "Puter — free, zero-config",
      hint: "No API key needed",
    },
    {
      value: "google",
      label: "Google — Gemini free tier",
      hint: "Sign in with Google",
    },
    {
      value: "apikey",
      label: "API key — subscription provider",
      hint: "OpenAI, Anthropic, Groq",
    },
  ];

  if (tier !== "cpu_only") {
    options.push({
      value: "local",
      label: "Local AI (Ollama)",
      hint: "Private, offline",
    });
  }

  options.push({
    value: "skip",
    label: "Skip for now",
    hint: "Set up a provider later",
  });

  return options;
}

/**
 * Main bootstrap function.
 *
 * Two paths:
 * 1. Nexus is already running on port 3100 — open the browser
 * 2. Fresh install — detect hardware, show provider options, print next steps
 */
export async function bootstrap(): Promise<void> {
  printBuildthisBanner();

  const port = 3100;

  // Non-TTY guard: prevent hanging in CI/piped environments
  if (!process.stdin.isTTY || !process.stdout.isTTY) {
    console.log(pc.bold("Run this command in an interactive terminal."));
    console.log("");
    console.log("  To open Nexus in your browser:");
    console.log(pc.cyan(`  http://127.0.0.1:${port}`));
    console.log("");
    console.log("  To install Nexus on this machine:");
    console.log(pc.cyan("  npx paperclipai@latest onboard"));
    process.exit(0);
    return;
  }

  // Path 1: Running instance detected
  const isRunning = await probeRunningInstance(port);
  if (isRunning) {
    const s = p.spinner();
    s.start("Opening Nexus...");
    const { default: open } = await import("open");
    await open(`http://127.0.0.1:${port}`);
    s.stop(pc.green("Nexus opened in your browser"));
    return;
  }

  // Path 2: Fresh install — detect hardware and guide setup
  const s = p.spinner();
  s.start("Detecting hardware...");
  const hw = await detectHardware();
  s.stop("Hardware detected");

  // Display hardware info
  if (hw.tier === "apple_silicon") {
    p.log.info(
      `${pc.bold("Apple Silicon detected")} — unified memory (${hw.totalGb} GB), runs entirely on your machine`
    );
  } else if (hw.tier === "gpu") {
    p.log.info(
      `${pc.bold("GPU detected")}: ${hw.gpuName} (${hw.gpuVramGb} GB VRAM) — ${hw.totalGb} GB RAM`
    );
  } else {
    p.log.info(
      `${pc.bold("CPU-only machine")} (${hw.totalGb} GB RAM) — cloud AI recommended for best experience`
    );
  }

  // Provider selection
  const provider = await p.select({
    message: "Which AI provider would you like to use?",
    options: getProviderOptions(hw.tier),
  });

  if (p.isCancel(provider)) {
    p.cancel("Cancelled");
    process.exit(0);
    return;
  }

  // Print next-step instructions
  console.log("");
  console.log(pc.bold("To install and start Nexus:"));
  console.log(pc.cyan("  npx paperclipai@latest onboard"));
  console.log("");

  if (provider === "local") {
    console.log(pc.dim("Make sure Ollama is installed: https://ollama.com"));
    console.log("");
  } else if (provider === "puter") {
    console.log(pc.dim("Puter provides free AI — no setup needed"));
    console.log("");
  }

  p.outro(pc.bold("Happy building!"));
}
