/*
 * run-langs.js — what the chat can display a *run result* for, one entry per
 * language.
 *
 * This is the display half of the execution track, and the counterpart to
 * languages.js. The distinction between the two is where the code runs:
 *
 *   languages.js  the fence IS the program; the browser runs it in a sandboxed
 *                 iframe, and this side has to build a document for it.
 *   run-langs.js  the program already ran, on the host, in synapse/code_run.py.
 *                 Nothing executes here — the fence carries source and captured
 *                 output as JSON, and this side only labels and lays it out.
 *
 * So an entry needs far less than a preview entry does: no toBody, no line
 * offsets, no runtime to inline. Just how to name the language to the reader.
 *
 * The backend keeps a matching registry (RUN_LANGS in synapse/code_run.py) that
 * says how each language is *executed*. Neither depends on the other at runtime;
 * tests/test_tools.py asserts the key sets stay equal.
 */

export const RUN_LANGS = {
  python: { label: "Python" },
  c: { label: "C" },
  cpp: { label: "C++" },
  rust: { label: "Rust" },
  erlang: { label: "Erlang" },
};

// The fence tag run_snippet emits. Not a real language: the block's body is the
// JSON envelope { lang, source, stdout, stderr, exit_code }, which keeps a run's
// output attached to the source that produced it. A model pasting the fence
// cannot paste output without the code, or code with output it never produced.
export const RUN_FENCE_LANG = "nexus-run";

/**
 * Parse a nexus-run fence body. Returns null for anything that isn't a
 * well-formed envelope naming a known language — the caller then falls back to
 * showing the block as plain code, which is the honest thing to do with a
 * result we can't vouch for.
 */
export function parseRunResult(text) {
  let data;
  try {
    data = JSON.parse(text);
  } catch {
    return null;
  }
  if (!data || typeof data !== "object") return null;
  if (!Object.prototype.hasOwnProperty.call(RUN_LANGS, data.lang)) return null;
  if (typeof data.source !== "string") return null;
  return {
    lang: data.lang,
    label: RUN_LANGS[data.lang].label,
    source: data.source,
    stdout: typeof data.stdout === "string" ? data.stdout : "",
    stderr: typeof data.stderr === "string" ? data.stderr : "",
    exitCode: Number.isInteger(data.exit_code) ? data.exit_code : null,
  };
}
