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

/* =====================================================================
   SECTION 06 — THE EMPTY GLOVE
   The provocation: every roll is a hallucination. Accuracy is just
   the cases where the roll happens to align with consensus reality.
   And asking the model to introspect doesn't escape the mechanism —
   it just runs the same machine on a different prompt.
   ===================================================================== */

const INTROSPECTION_PROMPTS = [
  "How do you work, exactly?",
  "Describe what happens inside you when you read this sentence.",
  "How do you decide which word to say next?",
  "Walk me through your reasoning process.",
  "How do you know the things you know?",
];

function IntrospectionDemo() {
  // Offline build serves a recorded-transcript variant — no Claude call.
  if (window.__OFFLINE && window.OfflineIntrospection) {
    const Offline = window.OfflineIntrospection;
    return <Offline />;
  }
  const [prompt, setPrompt] = useState(INTROSPECTION_PROMPTS[0]);
  const [working, setWorking] = useState(false);
  const [answer, setAnswer] = useState("");
  const [revealed, setRevealed] = useState(false);
  const [error, setError] = useState(null);

  const ask = useCallback(async () => {
    if (!prompt.trim() || working) return;
    setWorking(true);
    setAnswer("");
    setRevealed(false);
    setError(null);
    try {
      const reply = await window.claude.complete({
        messages: [
          { role: "user", content: `${prompt.trim()}\n\nKeep your answer to about 3-4 sentences. Be confident and direct.` },
        ],
      });
      setAnswer(reply.trim());
      // Reveal the reframe a beat after the answer renders, so the user
      // gets a moment to read it credulously before the floor moves.
      setTimeout(() => setRevealed(true), 1400);
    } catch (err) {
      setError(err.message || "Could not reach the model.");
    } finally {
      setWorking(false);
    }
  }, [prompt, working]);

  return (
    <div className="introspect">
      <div className="introspect-head">
        <div>
          <div className="mono" style={{ fontSize: 10, letterSpacing: "0.18em", textTransform: "uppercase", color: "var(--muted)", marginBottom: 8 }}>
            Ask the die to explain itself
          </div>
          <div style={{ fontFamily: "var(--serif-display)", fontSize: 26, lineHeight: 1.2, color: "var(--ink)" }}>
            “{prompt}”
          </div>
        </div>
        <button className="btn" onClick={ask} disabled={working}>
          {working ? "Rolling…" : "Roll the introspection die"}
        </button>
      </div>

      <div className="preset-row" style={{ marginTop: 14 }}>
        {INTROSPECTION_PROMPTS.map(p => (
          <button
            key={p}
            onClick={() => { setPrompt(p); setAnswer(""); setRevealed(false); }}
            className={p === prompt ? "active" : ""}
          >
            {p}
          </button>
        ))}
      </div>

      {error && (
        <div style={{ marginTop: 16, fontFamily: "var(--mono)", fontSize: 12, color: "var(--vermilion)" }}>
          ⚠ {error}
        </div>
      )}

      {(answer || working) && (
        <div className="introspect-answer">
          <div className="ans-label">
            <span>Claude says</span>
            <span className="meta">unedited · single roll</span>
          </div>
          <div className="ans-body">
            {working && !answer && <span style={{ color: "var(--muted)", fontStyle: "italic" }}>rolling…</span>}
            {answer}
          </div>

          {/* The reveal — overlays the answer with the reframe. */}
          {revealed && (
            <div className="ans-reveal">
              <div className="reveal-rule"></div>
              <div className="reveal-stamp">Mechanically identical to</div>
              <div className="reveal-compare">
                <div className="cmp">
                  <div className="cmp-prompt">“The capital of France is”</div>
                  <div className="cmp-out">Paris</div>
                  <div className="cmp-tag">a roll · we call this <i>accurate</i></div>
                </div>
                <div className="cmp">
                  <div className="cmp-prompt">“The capital of France is”</div>
                  <div className="cmp-out fab">banana</div>
                  <div className="cmp-tag">a roll · we call this a <i>hallucination</i></div>
                </div>
                <div className="cmp glove">
                  <div className="cmp-prompt">“{prompt}”</div>
                  <div className="cmp-out intro">↑ the answer above</div>
                  <div className="cmp-tag">a roll · we call this <i>introspection</i></div>
                </div>
              </div>
              <div className="reveal-line">
                Same die. Same math. No internal mirror was consulted.
                The model cannot read its own weights any more than
                you can read your own neurons. What it produced is a
                <i> statistically plausible string about how an AI
                works,</i> built from millions of articles, blog
                posts, and transcripts that describe AIs. The shape of
                the answer matches the shape of an explanation. That
                is all.
              </div>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

/* =====================================================================
   The "always hallucinating" reframe banner — clickable. Until clicked,
   the section reads like a normal continuation. After clicked, the
   entire framing flips and the reader is invited to look back.
   ===================================================================== */

function AlwaysHallucinatingReframe() {
  const [flipped, setFlipped] = useState(false);
  return (
    <div className={"reframe " + (flipped ? "flipped" : "")}>
      <div className="reframe-inner">
        <div className="reframe-side reframe-before">
          <div className="rf-eyebrow">The comfortable framing</div>
          <div className="rf-line">
            A hallucination is the die landing on a low-probability face.
            <span className="rf-hint">→ tap to push further</span>
          </div>
          <button className="rf-btn" onClick={() => setFlipped(true)}>
            Reframe →
          </button>
        </div>
        <div className="reframe-side reframe-after">
          <div className="rf-eyebrow" style={{ color: "var(--vermilion)" }}>The harder framing</div>
          <div className="rf-line">
            <i>Every</i> roll is a hallucination. <span className="strike">Accuracy</span> is the cases where the hallucination happens to align with consensus reality.
          </div>
          <button className="rf-btn" onClick={() => setFlipped(false)}>
            ← back
          </button>
        </div>
      </div>
    </div>
  );
}

Object.assign(window, { IntrospectionDemo, AlwaysHallucinatingReframe, GloveIllustration });

/* =====================================================================
   THE EMPTY GLOVE — a small SVG illustration. A glove silhouette with
   no hand inside, held up by invisible threads (the "statistical
   algorithms" controlling it). Restrained line drawing — not literal,
   not cute.
   ===================================================================== */

function GloveIllustration() {
  return (
    <svg viewBox="0 0 200 240" width="220" height="264" aria-label="An empty glove, held up by strings.">
      {/* puppet strings */}
      <g stroke="var(--vermilion)" strokeWidth="0.6" opacity="0.7" strokeDasharray="2 2">
        <line x1="50"  y1="0" x2="64"  y2="100" />
        <line x1="100" y1="0" x2="100" y2="90"  />
        <line x1="150" y1="0" x2="136" y2="100" />
      </g>
      {/* tiny knots where the strings attach */}
      <g fill="var(--vermilion)">
        <circle cx="64"  cy="100" r="1.6" />
        <circle cx="100" cy="90"  r="1.6" />
        <circle cx="136" cy="100" r="1.6" />
      </g>
      {/* glove outline — five fingers + cuff, hollow */}
      <g fill="none" stroke="var(--ink)" strokeWidth="1.4" strokeLinejoin="round" strokeLinecap="round">
        <path d="
          M 60 102
          L 56 60  Q 56 52, 62 52  Q 68 52, 68 60  L 70 100
          L 80 96
          L 78 44  Q 78 36, 86 36  Q 94 36, 94 44  L 94 96
          L 104 96
          L 102 30  Q 102 22, 110 22  Q 118 22, 118 30  L 118 100
          L 128 102
          L 128 56  Q 128 48, 134 48  Q 140 48, 140 56  L 140 108
          L 148 116
          L 152 96  Q 152 88, 158 88  Q 164 88, 164 96  L 162 130
          Q 162 170, 150 200
          L 56 200
          Q 44 170, 48 130
          Q 50 110, 60 102 Z
        " />
        {/* cuff hatching — quick parallel lines */}
        <line x1="62" y1="200" x2="62" y2="215" />
        <line x1="76" y1="200" x2="76" y2="218" />
        <line x1="90" y1="200" x2="90" y2="220" />
        <line x1="104" y1="200" x2="104" y2="220" />
        <line x1="118" y1="200" x2="118" y2="218" />
        <line x1="132" y1="200" x2="132" y2="215" />
        {/* cuff baseline */}
        <path d="M 50 220 Q 100 230, 152 220" />
      </g>
      {/* the "empty" inside — a soft, almost invisible hint of nothing */}
      <text x="100" y="155" textAnchor="middle"
        fontFamily="var(--mono)"
        fontSize="8"
        letterSpacing="0.2em"
        fill="var(--muted)"
        opacity="0.6">EMPTY</text>
    </svg>
  );
}
