/* global React */
const { useState, useEffect, useRef, useMemo, useCallback } = React;

// =============================================================
// Code block with simple Python-aware syntax highlighting
// =============================================================
function highlightPy(src) {
  // Tokenize line by line - simple regex based, good enough for snippets
  const KEYWORDS = new Set([
    "def","class","return","import","from","as","if","elif","else","for","while",
    "in","not","and","or","is","None","True","False","with","try","except","finally",
    "raise","yield","lambda","pass","break","continue","global","nonlocal","async","await"
  ]);
  // Process strings & comments first via spans so they don't get re-tokenized
  // Use placeholder approach
  const lines = src.split("\n");
  return lines.map((line, i) => {
    let out = "";
    let rest = line;
    // Comment
    const commentIdx = (() => {
      // very rough: find '#' not inside quotes
      let inS = null;
      for (let j=0; j<rest.length; j++) {
        const c = rest[j];
        if (inS) { if (c === inS && rest[j-1] !== "\\") inS = null; }
        else { if (c === '"' || c === "'") inS = c; else if (c === "#") return j; }
      }
      return -1;
    })();
    let codePart = rest, commentPart = "";
    if (commentIdx >= 0) {
      codePart = rest.slice(0, commentIdx);
      commentPart = rest.slice(commentIdx);
    }
    // Tokenize codePart
    const tokenRe = /("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*'|\b\d+\.?\d*\b|\b[A-Za-z_][A-Za-z_0-9]*\b|[(){}\[\],:.=+\-*/<>!@%&|^~]|\s+)/g;
    let m;
    while ((m = tokenRe.exec(codePart)) !== null) {
      const t = m[0];
      if (/^\s+$/.test(t)) { out += escapeHtml(t); continue; }
      if (/^["']/.test(t)) { out += `<span class="tok-str">${escapeHtml(t)}</span>`; continue; }
      if (/^\d/.test(t)) { out += `<span class="tok-num">${escapeHtml(t)}</span>`; continue; }
      if (/^[A-Za-z_]/.test(t)) {
        if (KEYWORDS.has(t)) { out += `<span class="tok-key">${t}</span>`; continue; }
        if (t === "self" || t === "cls") { out += `<span class="tok-op">${t}</span>`; continue; }
        // class-ish: starts uppercase
        if (/^[A-Z]/.test(t)) { out += `<span class="tok-cls">${t}</span>`; continue; }
        // function call: next char is '('
        const nextChar = codePart[m.index + t.length];
        if (nextChar === "(") { out += `<span class="tok-fn">${t}</span>`; continue; }
        out += `<span class="tok-var">${t}</span>`;
        continue;
      }
      if (/^[(){}\[\],:.]/.test(t)) { out += `<span class="tok-pun">${escapeHtml(t)}</span>`; continue; }
      out += `<span class="tok-op">${escapeHtml(t)}</span>`;
    }
    if (commentPart) out += `<span class="tok-com">${escapeHtml(commentPart)}</span>`;
    return out || "&nbsp;";
  }).join("\n");
}

function escapeHtml(s) {
  return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;");
}

function CodeBlock({ children, file = "example.py", lang = "python" }) {
  const html = useMemo(() => highlightPy(children.trim()), [children]);
  return (
    <div className="code-block">
      <div className="code-head">
        <span className="lang">{lang}</span>
        <span className="file">{file}</span>
      </div>
      <pre dangerouslySetInnerHTML={{ __html: html }} />
    </div>
  );
}

// =============================================================
// Callouts
// =============================================================
function Callout({ kind = "intuition", title, children }) {
  const labels = {
    intuition: "Intuition",
    warning: "Heads up",
    gotcha: "Gotcha",
    tip: "Pro tip",
    note: "Note",
  };
  return (
    <div className={`callout ${kind}`}>
      <div className="callout-label">{title || labels[kind]}</div>
      <div>{children}</div>
    </div>
  );
}

// =============================================================
// Diagram wrapper
// =============================================================
function Diagram({ title, controls, children }) {
  return (
    <div className="diagram">
      {(title || controls) && (
        <div className="diagram-title">
          <span>{title}</span>
          {controls && <span className="controls">{controls}</span>}
        </div>
      )}
      {children}
    </div>
  );
}

// =============================================================
// Section title with number
// =============================================================
function SectionTitle({ num, children, id }) {
  return (
    <h2 className="section-title" id={id}>
      {num && <span className="num">§ {num}</span>}
      {children}
    </h2>
  );
}

// Expose globally
Object.assign(window, {
  CodeBlock, Callout, Diagram, SectionTitle,
  highlightPy, escapeHtml,
});
