#!/usr/bin/env node
"use strict";
/**
 * Dev-only generator. Reads the canonical persona markdown at prompts/*.md and
 * writes the committed, bundle-safe core/prompts/index.js (a plain string map).
 *
 * This script is NEVER imported by the runtime or the esbuild bundle. The
 * generated core/prompts/index.js inlines every persona string so the bundle
 * carries them without any runtime fs / .md reads.
 *
 * Usage:
 *   node scripts/sync-prompts.js          # write core/prompts/index.js
 *   node scripts/sync-prompts.js --check  # exit 1 on drift, 0 if in sync
 */

const fs = require("fs");
const path = require("path");

/** The 8 personas: 7 expert tools plus the arbiter (data-only for now). */
const PERSONA_KEYS = [
  "architect",
  "plan-reviewer",
  "scope-analyst",
  "code-reviewer",
  "security-analyst",
  "researcher",
  "debugger",
  "arbiter",
];

const REPO_ROOT = path.resolve(__dirname, "..");
const PROMPTS_DIR = path.join(REPO_ROOT, "prompts");
const OUT_FILE = path.join(REPO_ROOT, "core", "prompts", "index.js");

/**
 * Read every persona markdown and return a { key: string } map.
 * @param {string} [promptsDir]
 * @returns {Record<string, string>}
 */
function readPersonas(promptsDir) {
  const dir = promptsDir || PROMPTS_DIR;
  /** @type {Record<string, string>} */
  const map = {};
  for (const key of PERSONA_KEYS) {
    const file = path.join(dir, `${key}.md`);
    map[key] = fs.readFileSync(file, "utf8").replace(/\r\n/g, "\n").replace(/\s+$/, "") + "\n";
  }
  return map;
}

/**
 * Render the committed core/prompts/index.js source from a persona map.
 * Personas are emitted as JSON-encoded string literals so esbuild inlines them
 * and the result is valid strict-checked JS.
 * @param {Record<string, string>} personas
 * @returns {string}
 */
function renderModule(personas) {
  const entries = PERSONA_KEYS.map((key) => `  ${JSON.stringify(key)}: ${JSON.stringify(personas[key])},`).join("\n");
  return [
    '"use strict";',
    "// GENERATED by scripts/sync-prompts.js from prompts/*.md - do not edit by hand.",
    "// Persona strings are inlined here so the MCP bundle carries them with no runtime fs/.md reads.",
    "",
    "/** @type {Record<string, string>} */",
    "const PROMPTS = {",
    entries,
    "};",
    "",
    "module.exports = { PROMPTS };",
    "",
  ].join("\n");
}

function main() {
  const check = process.argv.includes("--check");
  const personas = readPersonas();
  const source = renderModule(personas);
  const rel = path.relative(REPO_ROOT, OUT_FILE);

  if (check) {
    const onDisk = fs.existsSync(OUT_FILE) ? fs.readFileSync(OUT_FILE, "utf8").replace(/\r\n/g, "\n") : null;
    if (onDisk !== source) {
      process.stderr.write(`generated persona module out of date - run \`node scripts/sync-prompts.js\`:\n  - ${rel}\n`);
      process.exit(1);
    }
    process.stdout.write(`persona module up to date (${PERSONA_KEYS.length} personas)\n`);
    return;
  }

  fs.mkdirSync(path.dirname(OUT_FILE), { recursive: true });
  fs.writeFileSync(OUT_FILE, source);
  process.stdout.write(`wrote ${rel} (${PERSONA_KEYS.length} personas)\n`);
}

if (require.main === module) main();

module.exports = { PERSONA_KEYS, readPersonas, renderModule, PROMPTS_DIR, OUT_FILE };
