"use strict";

const fs = require("fs");
const path = require("path");
const { execFileSync } = require("child_process");

const { getTheme } = require("./logging");

// ─── Windows npm PATH detection ─────────────────────────────────────────────

/**
 * On Windows, decide whether the freshly-installed `evolv-coder-kit` shim is
 * reachable as a bare command. The shim lives at <APPDATA>\\npm\\evolv-coder-kit.cmd
 * and only resolves if <APPDATA>\\npm is on PATH — not guaranteed on Windows
 * installs where Node was set up without updating the user PATH.
 *
 * Pure function with DI for testability — no real fs/exec calls unless the
 * caller omits the implementations. Returns:
 *   { shouldWarn: false } when not on Windows, or APPDATA missing, or the
 *     shim doesn't exist (someone installed via a non-standard path — no
 *     useful warning to give), or the bare command resolves;
 *   { shouldWarn: true, npmPrefix, shimPath } when the shim is laid down
 *     but `where.exe evolv-coder-kit` returns no result.
 *
 * Only Windows is checked — Linux/macOS npm prefixes are typically on PATH
 * by default, and false-positives on those platforms aren't worth the noise.
 */
function checkNpmPrefixOnPath(opts = {}) {
  const platform = opts.platform || process.platform;
  if (platform !== "win32") return { shouldWarn: false };

  const env = opts.env || process.env;
  const appData = env.APPDATA;
  if (!appData) return { shouldWarn: false };

  // Windows-only contract — use path.win32 so paths render with backslashes
  // regardless of host OS (matters for tests on Linux/macOS CI runners and
  // for the warning message displayed to Windows users).
  const npmPrefix = path.win32.join(appData, "npm");
  const shimPath = path.win32.join(npmPrefix, "evolv-coder-kit.cmd");

  const shimExists = opts.shimExists
    ? opts.shimExists(shimPath)
    : fs.existsSync(shimPath);
  if (!shimExists) return { shouldWarn: false };

  const isCliReachable =
    opts.isCliReachable ||
    (() => {
      try {
        execFileSync("where.exe", ["evolv-coder-kit"], {
          stdio: ["ignore", "ignore", "ignore"],
        });
        return true;
      } catch {
        return false;
      }
    });

  if (isCliReachable()) return { shouldWarn: false };

  return { shouldWarn: true, npmPrefix, shimPath };
}

/**
 * Print the npm-prefix-not-on-PATH warning given a check result. No-op when
 * shouldWarn is false. Theme defaults to the current install theme.
 */
function printNpmPrefixWarning(checkResult, theme) {
  if (!checkResult || !checkResult.shouldWarn) return;
  const t = theme || getTheme();
  console.log("");
  console.log(
    `  ${t.bold("Warning:")} evolv-coder-kit is installed but not on PATH`,
  );
  console.log("");
  console.log(`  Shim:        ${checkResult.shimPath}`);
  console.log(`  npm prefix:  ${checkResult.npmPrefix}`);
  console.log("");
  console.log(`  The bare command 'evolv-coder-kit' will not resolve in a new`);
  console.log(
    `  shell until you add the npm prefix above to your Windows PATH.`,
  );
  console.log("");
  console.log(`  To fix (one-time):`);
  console.log(`    1. Open System Settings  →  Environment Variables`);
  console.log(
    `    2. Edit your User 'Path' variable; add the npm prefix above`,
  );
  console.log(`    3. Restart your shell`);
  console.log("");
  console.log(`  Or invoke by full path until then:`);
  console.log(`    ${checkResult.shimPath} --help`);
  console.log("");
}

module.exports = {
  checkNpmPrefixOnPath,
  printNpmPrefixWarning,
};
