// Sanity checks for the VS Code extension assets. Run with `node test/validate.mjs`.
// Verifies the JSON contribution files parse and that the bundled compiler both
// accepts valid .wrn and reports an offset for invalid .wrn (what diagnostics need).
import { readFileSync } from "node:fs";
import { fileURLToPath } from "node:url";
import { dirname, join } from "node:path";
import { createRequire } from "node:module";

const here = dirname(fileURLToPath(import.meta.url));
const root = join(here, "..");
const require = createRequire(import.meta.url);

let failures = 0;
const ok = (name) => console.log(`  ok   ${name}`);
const bad = (name, detail) => {
  failures++;
  console.error(`  FAIL ${name}${detail ? " — " + detail : ""}`);
};

// 1. All JSON contribution files parse.
for (const rel of [
  "package.json",
  "language-configuration.json",
  "syntaxes/wrn.tmLanguage.json",
  "syntaxes/wrn.injection.tmLanguage.json",
  "snippets/wrn.json",
]) {
  try {
    JSON.parse(readFileSync(join(root, rel), "utf8"));
    ok(`json parses: ${rel}`);
  } catch (e) {
    bad(`json parses: ${rel}`, e.message);
  }
}

// 2. Grammar wires up the right scope + embedded languages.
const grammar = JSON.parse(readFileSync(join(root, "syntaxes/wrn.tmLanguage.json"), "utf8"));
grammar.scopeName === "source.wrn" ? ok("grammar scopeName") : bad("grammar scopeName");

// 3. Marketplace metadata and the gallery icon meet vsce requirements.
try {
  const manifest = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
  manifest.publisher === "wrnexus" ? ok("publisher id") : bad("publisher id");
  manifest.icon?.endsWith(".png") ? ok("Marketplace icon is PNG") : bad("Marketplace icon is PNG");
  const icon = readFileSync(join(root, manifest.icon));
  const isPng = icon.subarray(1, 4).toString("ascii") === "PNG";
  const width = isPng ? icon.readUInt32BE(16) : 0;
  const height = isPng ? icon.readUInt32BE(20) : 0;
  isPng && width >= 128 && height >= 128
    ? ok(`Marketplace icon dimensions (${width}x${height})`)
    : bad("Marketplace icon is at least 128x128 PNG");
  for (const rel of ["README.md", "CHANGELOG.md", "SUPPORT.md", "LICENSE"]) {
    readFileSync(join(root, rel), "utf8");
    ok(`Marketplace document exists: ${rel}`);
  }
} catch (e) {
  bad("Marketplace metadata", e.message);
}

// 4. Bundled compiler: valid source compiles, invalid source throws with an offset.
try {
  const compiler = require(join(root, "src/compiler.cjs"));
  const good = `page Home {\n  view { <h1>Hi</h1> }\n}`;
  compiler.compileWireFile(good);
  ok("compiler accepts valid .wrn");

  const badSrc = `page Home {\n  view { <h1>Hi</h2> }\n}`;
  let threw = false;
  try {
    compiler.compileWireFile(badSrc);
  } catch (e) {
    threw = true;
    /offset\s+\d+|end of input/.test(e.message)
      ? ok("compiler reports a locatable error")
      : bad("compiler reports a locatable error", e.message);
  }
  if (!threw) bad("compiler rejects invalid .wrn");
} catch (e) {
  bad("compiler bundle loads", e.message);
}

// 5. Formatter normalizes nested WRN blocks and is idempotent.
try {
  const { formatWrn } = require(join(root, "src/formatter.js"));
  const source = `page Home {\nview {\n<main>\n<h1>Hello</h1>\n</main>\n}\n}\n`;
  const expected = `page Home {\n  view {\n    <main>\n      <h1>Hello</h1>\n    </main>\n  }\n}\n`;
  const formatted = formatWrn(source, { insertSpaces: true, tabSize: 2 });
  formatted === expected ? ok("formatter indents WRN blocks") : bad("formatter indents WRN blocks");
  formatWrn(formatted, { insertSpaces: true, tabSize: 2 }) === formatted
    ? ok("formatter is idempotent")
    : bad("formatter is idempotent");
} catch (e) {
  bad("formatter loads", e.message);
}

console.log(failures === 0 ? "\nAll extension checks passed." : `\n${failures} check(s) failed.`);
process.exit(failures === 0 ? 0 : 1);
