"use strict";

const readline = require("readline");
const { displayLogo } = require("./logo");
const { renderBox } = require("./box");

const OUTPUT_MODE_OPTIONS = [
  {
    value: "guided",
    label: "Guided",
    hint: "Detailed explanations, examples for every field",
  },
  {
    value: "standard",
    label: "Standard",
    hint: "Balanced — action first, brief context",
  },
  { value: "concise", label: "Concise", hint: "Code-first, minimal prose" },
  {
    value: "pair",
    label: "Pair",
    hint: "Think aloud, invite feedback, collaborative",
  },
  {
    value: "review",
    label: "Review",
    hint: "Severity-tagged findings, structured feedback",
  },
];

const DEV_RIGOR_OPTIONS = [
  {
    value: "lite",
    label: "Lite",
    hint: "Spike / PoC — skip TDD, security, heavy docs",
  },
  {
    value: "standard",
    label: "Standard",
    hint: "MVP — balanced quality gates",
  },
  {
    value: "strict",
    label: "Strict",
    hint: "Production — full TDD, security, docs",
  },
];

const PROTECTION_OPTIONS = [
  {
    value: "disable",
    label: "Disabled",
    hint: "No safety hooks — fastest workflow",
  },
  {
    value: "enable",
    label: "Enabled",
    hint: "File protection, secret detection, HITL approval, security gate",
  },
];

const OVERWRITE_OPTIONS = [
  {
    value: "update",
    label: "Update",
    hint: "Copy new files, keep existing customizations",
  },
  {
    value: "overwrite",
    label: "Full reinstall",
    hint: "Overwrite all files with defaults",
  },
  { value: "skip", label: "Skip", hint: "Exit without changes" },
];

/**
 * Run the install interview wizard.
 * Dynamically imports @clack/prompts (ESM) from a CJS module.
 * Falls back to readline if the import fails.
 */
async function runInterview(options = {}) {
  // Non-TTY contexts (piped/redirected) skip clack prompts to avoid garbled output
  if (!process.stdout.isTTY) {
    return await runReadlineInterview(options);
  }
  try {
    const clack = await import("@clack/prompts");
    return await runClackInterview(clack, options);
  } catch (err) {
    process.stderr.write(
      `[ECK] Note: @clack/prompts unavailable (${err.code || err.message}). ` +
        `Using text prompts.\n`,
    );
    return await runReadlineInterview(options);
  }
}

/**
 * Clack-powered interview path (rich UI).
 */
async function runClackInterview(clack, options = {}) {
  const { existingInstall = false, currentVersion } = options;

  // Screen 0: Logo — write directly, not via clack.intro() which adds a ┌ box frame
  const logoText = displayLogo({ showTagline: true, showVersion: true });
  process.stdout.write(logoText);

  // Screen 1: Tool selector — auto-select claude-code (single option)
  // This screen will return when multi-tool support lands
  const tool = "claude-code";

  // Screen 2: Output mode
  const outputMode = await clack.select({
    message: "Which output mode do you prefer?",
    options: OUTPUT_MODE_OPTIONS,
    initialValue: "standard",
  });
  if (clack.isCancel(outputMode)) {
    clack.cancel("Installation cancelled.");
    process.exit(0);
  }

  // Screen 3: Dev rigor
  const devRigor = await clack.select({
    message: "Which dev rigor level should be the default?",
    options: DEV_RIGOR_OPTIONS,
    initialValue: "standard",
  });
  if (clack.isCancel(devRigor)) {
    clack.cancel("Installation cancelled.");
    process.exit(0);
  }

  // Screen 4: Safety protections
  const protections = await clack.select({
    message:
      "Enable safety protections (hook-based file protection, secret detection, HITL approval)?",
    options: PROTECTION_OPTIONS,
    initialValue: "disable",
  });
  if (clack.isCancel(protections)) {
    clack.cancel("Installation cancelled.");
    process.exit(0);
  }

  // Screen 5: Overwrite mode (conditional)
  let overwriteMode;
  if (existingInstall) {
    const versionNote = currentVersion ? ` v${currentVersion}` : "";
    overwriteMode = await clack.select({
      message: `ECK${versionNote} is already installed. What would you like to do?`,
      options: OVERWRITE_OPTIONS,
    });
    if (clack.isCancel(overwriteMode)) {
      clack.cancel("Installation cancelled.");
      process.exit(0);
    }
    if (overwriteMode === "skip") {
      clack.outro("No changes made.");
      return buildResult({
        tool,
        outputMode,
        devRigor,
        protections,
        overwriteMode,
      });
    }
  }

  // Screen 6: Confirmation
  const modeLabelName =
    OUTPUT_MODE_OPTIONS.find((o) => o.value === outputMode)?.label ||
    outputMode;
  const devRigorName =
    DEV_RIGOR_OPTIONS.find((o) => o.value === devRigor)?.label || devRigor;
  const protectionName =
    PROTECTION_OPTIONS.find((o) => o.value === protections)?.label ||
    protections;
  const summaryItems = [
    { label: "Tool", value: "Claude Code" },
    { label: "Output Mode", value: modeLabelName },
    { label: "Dev Rigor", value: devRigorName },
    { label: "Protections", value: protectionName },
  ];
  if (overwriteMode) {
    summaryItems.push({ label: "Overwrite", value: overwriteMode });
  }

  const boxOutput = renderBox({
    title: "Installation Plan",
    items: summaryItems,
  });
  clack.note(boxOutput);

  const confirmed = await clack.confirm({
    message: "Proceed with installation?",
  });
  if (clack.isCancel(confirmed) || !confirmed) {
    clack.cancel("Installation cancelled.");
    process.exit(0);
  }

  clack.outro("Starting installation...");

  return buildResult({
    tool,
    outputMode,
    devRigor,
    protections,
    overwriteMode,
  });
}

/**
 * Readline fallback interview path (plain text).
 */
async function runReadlineInterview(options = {}) {
  const { existingInstall = false, currentVersion } = options;

  const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });

  const onSigint = () => {
    console.log("\nInstallation cancelled.");
    rl.close();
    process.exit(0);
  };
  process.on("SIGINT", onSigint);

  const ask = (question) =>
    new Promise((resolve) => rl.question(question, resolve));

  function selectMenu(prompt, opts) {
    console.log(`\n${prompt}`);
    opts.forEach((o, i) => {
      const hint = o.hint ? ` (${o.hint})` : "";
      console.log(`  ${i + 1}) ${o.label}${hint}`);
    });
    return ask(`Enter number [1]: `).then((answer) => {
      const idx = parseInt(answer.trim(), 10) - 1;
      if (idx >= 0 && idx < opts.length) return opts[idx].value;
      return opts[0].value;
    });
  }

  // Logo
  const logoText = displayLogo({ showTagline: true, showVersion: true });
  console.log(logoText);

  // Screen 1: Tool — auto-select claude-code (single option)
  // This screen will return when multi-tool support lands
  const tool = "claude-code";

  // Screen 2: Output mode
  const outputMode = await selectMenu(
    "Which output mode do you prefer?",
    OUTPUT_MODE_OPTIONS,
  );

  // Screen 3: Dev rigor
  const devRigor = await selectMenu(
    "Which dev rigor level should be the default?",
    DEV_RIGOR_OPTIONS,
  );

  // Screen 4: Safety protections
  const protections = await selectMenu(
    "Enable safety protections (file protection, secret detection, HITL approval)?",
    PROTECTION_OPTIONS,
  );

  // Screen 5: Overwrite (conditional)
  let overwriteMode;
  if (existingInstall) {
    const versionNote = currentVersion ? ` v${currentVersion}` : "";
    overwriteMode = await selectMenu(
      `ECK${versionNote} is already installed. What would you like to do?`,
      OVERWRITE_OPTIONS,
    );
    if (overwriteMode === "skip") {
      console.log("\nNo changes made.");
      rl.close();
      process.removeListener("SIGINT", onSigint);
      return buildResult({
        tool,
        outputMode,
        devRigor,
        protections,
        overwriteMode,
      });
    }
  }

  // Screen 6: Confirmation
  const modeLabelName =
    OUTPUT_MODE_OPTIONS.find((o) => o.value === outputMode)?.label ||
    outputMode;
  const devRigorName =
    DEV_RIGOR_OPTIONS.find((o) => o.value === devRigor)?.label || devRigor;
  const protectionName =
    PROTECTION_OPTIONS.find((o) => o.value === protections)?.label ||
    protections;
  const summaryItems = [
    { label: "Tool", value: "Claude Code" },
    { label: "Output Mode", value: modeLabelName },
    { label: "Dev Rigor", value: devRigorName },
    { label: "Protections", value: protectionName },
  ];
  if (overwriteMode) {
    summaryItems.push({ label: "Overwrite", value: overwriteMode });
  }

  console.log(
    "\n" + renderBox({ title: "Installation Plan", items: summaryItems }),
  );

  const confirmAnswer = await ask("\nProceed with installation? (Y/n): ");
  if (confirmAnswer.trim().toLowerCase() === "n") {
    console.log("Installation cancelled.");
    rl.close();
    process.removeListener("SIGINT", onSigint);
    process.exit(0);
  }

  rl.close();
  process.removeListener("SIGINT", onSigint);

  return buildResult({
    tool,
    outputMode,
    devRigor,
    protections,
    overwriteMode,
  });
}

/**
 * Build the InterviewResult object.
 */
function buildResult({
  tool,
  outputMode,
  devRigor,
  protections,
  overwriteMode,
}) {
  const result = {
    tool,
    outputMode,
    devRigor,
    protections: protections || "disable",
  };
  if (overwriteMode !== undefined) {
    result.overwriteMode = overwriteMode;
  }
  return result;
}

module.exports = { runInterview, runClackInterview, runReadlineInterview };
