import { formatDuration, markNativeReady, required } from "./shared/shell.ts";

markNativeReady();

type ExampleName = "dom" | "types" | "async" | "error";
const examples: Record<ExampleName, string> = {
  dom: `interface Meter {\n  label: string;\n  value: number;\n  color: string;\n}\n\nexport function run(host: HTMLElement): void {\n  const meters: Meter[] = [\n    { label: "Parse", value: 92, color: "#55d5dc" },\n    { label: "Resolve", value: 78, color: "#b6df63" },\n    { label: "Execute", value: 100, color: "#ff645f" },\n  ];\n\n  for (const meter of meters) {\n    const row = document.createElement("div");\n    row.style.cssText = "display:grid;grid-template-columns:80px 1fr 42px;gap:10px;align-items:center;margin:12px 0;font:12px ui-monospace,monospace";\n    row.innerHTML = \`<span>\${meter.label}</span><span style="height:8px;background:#242c31"><i style="display:block;width:\${meter.value}%;height:100%;background:\${meter.color}"></i></span><b>\${meter.value}%</b>\`;\n    host.append(row);\n  }\n}`,
  types: `type Result<T> = { ok: true; value: T } | { ok: false; reason: string };\n\nfunction parsePort(value: string): Result<number> {\n  const port = Number(value);\n  return Number.isInteger(port) && port > 0 && port < 65536\n    ? { ok: true, value: port }\n    : { ok: false, reason: "Invalid TCP port" };\n}\n\nexport function run(host: HTMLElement): void {\n  const result = parsePort("8788");\n  host.textContent = result.ok\n    ? \`Listening on typed port \${result.value}\`\n    : result.reason;\n}`,
  async: `interface EventRecord { id: number; phase: "parse" | "check" | "emit" }\n\nconst wait = (ms: number): Promise<void> => new Promise(resolve => setTimeout(resolve, ms));\n\nexport async function run(host: HTMLElement): Promise<void> {\n  const events: EventRecord[] = [\n    { id: 1, phase: "parse" },\n    { id: 2, phase: "check" },\n    { id: 3, phase: "emit" },\n  ];\n  for (const event of events) {\n    await wait(180);\n    host.append(\`✓ \${event.id}: \${event.phase}\\n\`);\n  }\n}`,
  error: `interface User { id: number; name: string }\n\nexport function run(host: HTMLElement): void {\n  const user: User = { id: 7, name: "Ada" };\n  host.textContent = user.name;\n  throw new Error("Intentional runtime error: visible by default");\n}`,
};

const editor = required<HTMLTextAreaElement>("[data-editor]");
const host = required<HTMLElement>("[data-output-host]");
const log = required<HTMLElement>("[data-log]");
const meta = required<HTMLElement>("[data-run-meta]");
editor.value = examples.dom;

document.querySelectorAll<HTMLButtonElement>("[data-example]").forEach((button) => {
  button.addEventListener("click", () => {
    const key = button.dataset.example as ExampleName;
    editor.value = examples[key];
    document.querySelectorAll("[data-example]").forEach((item) => item.classList.remove("is-active"));
    button.classList.add("is-active");
  });
});

required<HTMLButtonElement>("[data-run]").addEventListener("click", async () => {
  host.replaceChildren();
  log.textContent = "";
  meta.textContent = "Importing TypeScript module...";
  const started = performance.now();
  try {
    const url = `data:text/typescript;charset=utf-8,${encodeURIComponent(editor.value)}#${Date.now()}`;
    const module = await import(url);
    if (typeof module.run !== "function") throw new TypeError("Module must export run(host: HTMLElement)");
    await module.run(host);
    meta.textContent = `Completed in ${formatDuration(performance.now() - started)}`;
    meta.style.color = "#b6df63";
  } catch (error) {
    log.textContent = `\n${error instanceof Error ? `${error.name}: ${error.message}\n${error.stack ?? ""}` : String(error)}`;
    meta.textContent = `Failed in ${formatDuration(performance.now() - started)}`;
    meta.style.color = "#ff645f";
  }
});

required<HTMLButtonElement>("[data-clear]").addEventListener("click", () => {
  host.textContent = "Output cleared.";
  log.textContent = "";
  meta.textContent = "Waiting for execution";
  meta.style.color = "";
});
