"use strict";

/* eslint-disable @typescript-eslint/no-require-imports -- Node SEA CommonJS entry point */

const { spawnSync } = require("node:child_process");
const { existsSync, readdirSync, readFileSync } = require("node:fs");
const { dirname, join } = require("node:path");
const readline = require("node:readline/promises");

function isProject(directory) {
  const packagePath = join(directory, "package.json");
  if (!existsSync(packagePath)) return false;
  try {
    return JSON.parse(readFileSync(packagePath, "utf8")).name === "factorio-production-calculator";
  } catch {
    return false;
  }
}

function findProject() {
  const candidates = [...new Set([dirname(process.execPath), process.cwd()])];
  for (const directory of candidates) {
    if (isProject(directory)) return directory;
    try {
      for (const entry of readdirSync(directory, { withFileTypes: true })) {
        if (entry.isDirectory() && isProject(join(directory, entry.name))) {
          return join(directory, entry.name);
        }
      }
    } catch {
      // Continue with the next candidate.
    }
  }
  return null;
}

function runCommand(project, command) {
  console.log(`\n> ${command}\n`);
  const result = spawnSync(
    process.env.ComSpec || "cmd.exe",
    ["/d", "/s", "/c", command],
    { cwd: project, stdio: "inherit", windowsHide: false },
  );
  if (result.error) {
    console.error(`Start failed / Start fehlgeschlagen: ${result.error.message}`);
    return false;
  }
  if (result.status !== 0) {
    console.error(`\nCommand failed with exit code ${result.status}. / Befehl fehlgeschlagen.`);
    return false;
  }
  return true;
}

function nodeAvailable(project) {
  const result = spawnSync(
    process.env.ComSpec || "cmd.exe",
    ["/d", "/s", "/c", "node --version && npm.cmd --version"],
    { cwd: project, stdio: "inherit", windowsHide: false },
  );
  return result.status === 0;
}

async function pause(interface_) {
  await interface_.question("\nPress Enter to continue / Enter zum Fortfahren ... ");
}

async function main() {
  process.title = "Factorio Calculator Source Tools 1.0.0";
  const project = findProject();
  if (!project) {
    console.error("Factorio source folder not found. / Factorio-Quellordner nicht gefunden.");
    console.error("Place this EXE inside the extracted source folder beside package.json.");
    console.error("Lege diese EXE in den entpackten Quellordner neben package.json.");
    const interface_ = readline.createInterface({ input: process.stdin, output: process.stdout });
    await interface_.question("\nEnter zum Beenden ... ");
    interface_.close();
    process.exitCode = 1;
    return;
  }

  console.log("Factorio Calculator Source Tools 1.0.0");
  console.log(`Project / Projekt: ${project}`);
  if (!nodeAvailable(project)) {
    console.error("\nNode.js 22.13 or newer with npm is required.");
    console.error("Node.js 22.13 oder neuer einschließlich npm wird benötigt.");
    console.error("Download: https://nodejs.org/en/download");
    const interface_ = readline.createInterface({ input: process.stdin, output: process.stdout });
    await interface_.question("\nEnter zum Beenden ... ");
    interface_.close();
    process.exitCode = 1;
    return;
  }

  const interface_ = readline.createInterface({ input: process.stdin, output: process.stdout });
  while (true) {
    console.log("\n1  Install exact dependencies / Abhängigkeiten installieren (npm ci)");
    console.log("2  Start local development / Lokal entwickeln");
    console.log("3  Build and verify STRATO website / STRATO-Website bauen und prüfen");
    console.log("4  Run all tests / Alle Tests ausführen");
    console.log("5  Create release ZIPs / Release-ZIPs erzeugen");
    console.log("6  Open STRATO output folder / STRATO-Ausgabeordner öffnen");
    console.log("0  Exit / Beenden");
    const choice = (await interface_.question("\nSelection / Auswahl: ")).trim();

    if (choice === "0") break;
    if (choice === "1") runCommand(project, "npm.cmd ci");
    else if (choice === "2") {
      if (!existsSync(join(project, "node_modules")) && !runCommand(project, "npm.cmd ci")) {
        await pause(interface_);
        continue;
      }
      runCommand(project, "npm.cmd run local");
    } else if (choice === "3") {
      if (runCommand(project, "npm.cmd run build:strato")) {
        runCommand(project, "npm.cmd run verify:strato");
      }
    } else if (choice === "4") runCommand(project, "npm.cmd test");
    else if (choice === "5") runCommand(project, "npm.cmd run package:release");
    else if (choice === "6") {
      const output = join(project, "strato-dist");
      if (existsSync(output)) runCommand(project, `explorer.exe "${output}"`);
      else console.error("Build folder does not exist yet. / Der Build-Ordner existiert noch nicht.");
    } else {
      console.log("Unknown selection / Unbekannte Auswahl");
    }
    if (choice !== "2") await pause(interface_);
  }
  interface_.close();
}

main().catch((error) => {
  console.error(error);
  process.exitCode = 1;
});
