/**
 * Minimal markdown → HTML for LLM output.
 * Handles: code blocks, inline code, bold, italic, links, lists, headings, paragraphs.
 * No dependencies. ~80 lines.
 *
 * Usage:
 *   import { renderMarkdown } from './markdown.js';
 *   element.innerHTML = renderMarkdown(text);
 */

const ESC = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' };
const esc = (s) => s.replace(/[&<>"]/g, (c) => ESC[c]);

export function renderMarkdown(src) {
  const lines = src.split('\n');
  const out = [];
  let i = 0;

  while (i < lines.length) {
    const line = lines[i];

    // Fenced code block — when a language is named, emit <code-ui> so
    // the site picks up the syntax-highlight upgrade shipped in
    // SPEC-CODE-EDITOR-001. Unlabeled fences keep the bare <pre><code>
    // form (no highlight needed; zero CM6 cost).
    const fence = line.match(/^```(\w*)/);
    if (fence) {
      const lang = fence[1];
      const code = [];
      i++;
      while (i < lines.length && !lines[i].startsWith('```')) {
        code.push(esc(lines[i]));
        i++;
      }
      i++; // skip closing ```
      const body = code.join('\n');
      out.push(lang
        ? `<code-ui language="${lang}">${body}</code-ui>`
        : `<pre><code>${body}</code></pre>`);
      continue;
    }

    // Empty line
    if (!line.trim()) { i++; continue; }

    // Heading
    const h = line.match(/^(#{1,6})\s+(.+)/);
    if (h) {
      const level = h[1].length;
      out.push(`<h${level}>${inline(h[2])}</h${level}>`);
      i++;
      continue;
    }

    // Unordered list
    if (/^[-*]\s/.test(line)) {
      const items = [];
      while (i < lines.length && /^[-*]\s/.test(lines[i])) {
        items.push(`<li>${inline(lines[i].replace(/^[-*]\s/, ''))}</li>`);
        i++;
      }
      out.push(`<ul>${items.join('')}</ul>`);
      continue;
    }

    // Ordered list
    if (/^\d+\.\s/.test(line)) {
      const items = [];
      while (i < lines.length && /^\d+\.\s/.test(lines[i])) {
        items.push(`<li>${inline(lines[i].replace(/^\d+\.\s/, ''))}</li>`);
        i++;
      }
      out.push(`<ol>${items.join('')}</ol>`);
      continue;
    }

    // Paragraph (collect consecutive non-empty, non-special lines)
    const para = [];
    while (i < lines.length && lines[i].trim() && !/^```|^#{1,6}\s|^[-*]\s|^\d+\.\s/.test(lines[i])) {
      para.push(lines[i]);
      i++;
    }
    out.push(`<p>${inline(para.join(' '))}</p>`);
  }

  return out.join('\n');
}

function inline(text) {
  return esc(text)
    // Bold **text** or __text__
    .replace(/\*\*(.+?)\*\*/g, '<strong>$1</strong>')
    .replace(/__(.+?)__/g, '<strong>$1</strong>')
    // Italic *text* or _text_
    .replace(/\*(.+?)\*/g, '<em>$1</em>')
    .replace(/_(.+?)_/g, '<em>$1</em>')
    // Inline code `code`
    .replace(/`([^`]+)`/g, '<code>$1</code>')
    // Links [text](url)
    .replace(/\[([^\]]+)\]\(([^)]+)\)/g, '<a href="$2">$1</a>');
}
