// ui-bits.jsx — Shared UI primitives for the parents guide.

const { useState, useEffect, useRef } = React;

// ── tiny utils ──────────────────────────────────────────────────────────────
function cls(...xs) { return xs.filter(Boolean).join(" "); }
function readLS(key, fallback) {
  try { const v = localStorage.getItem(key); return v == null ? fallback : JSON.parse(v); }
  catch { return fallback; }
}
function writeLS(key, value) {
  try { localStorage.setItem(key, JSON.stringify(value)); } catch {}
}

// ── HandUnderline: a wobbly hand-drawn underline ────────────────────────────
function HandUnderline({ color = "currentColor", width = 200, height = 12, style }) {
  return (
    <svg viewBox="0 0 200 12" width={width} height={height}
         preserveAspectRatio="none" aria-hidden="true"
         style={{ display: "block", overflow: "visible", ...style }}>
      <path d="M2,7 C 40,3 80,10 120,5 C 150,2 180,9 198,5"
            fill="none" stroke={color} strokeWidth="2.2" strokeLinecap="round" />
    </svg>
  );
}

// ── Circle stamp number — "Station 03" style ────────────────────────────────
function StationStamp({ number, color, size = 96 }) {
  const id = `stamp-${number}-${size}`;
  const radius = size * 0.42;
  const cx = size / 2, cy = size / 2;
  return (
    <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} aria-hidden="true">
      <defs>
        <path id={id} d={`M ${cx - radius},${cy} a ${radius},${radius} 0 1,1 ${radius * 2},0 a ${radius},${radius} 0 1,1 -${radius * 2},0`} />
      </defs>
      <circle cx={cx} cy={cy} r={radius + 4} fill="none" stroke={color} strokeWidth="1.5" strokeDasharray="3 4" opacity="0.5" />
      <circle cx={cx} cy={cy} r={radius - 4} fill="none" stroke={color} strokeWidth="2" />
      <text textAnchor="middle" fill={color}
            style={{ fontFamily: "var(--f-display)", fontWeight: 800, fontStyle: "italic" }}
            x={cx} y={cy + size * 0.12} fontSize={size * 0.42}>
        {String(number).padStart(2, "0")}
      </text>
      <text fill={color}
            style={{ fontFamily: "var(--f-body)", fontWeight: 700, letterSpacing: "0.22em" }}
            fontSize={size * 0.085}>
        <textPath href={`#${id}`} startOffset="50%" textAnchor="middle">
          · STATION · STATION ·
        </textPath>
      </text>
    </svg>
  );
}

// ── ProgressDots: 5 stations done/not ───────────────────────────────────────
function ProgressDots({ stations, completed, onJump }) {
  return (
    <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
      {stations.map((s) => {
        const done = completed.has(s.id);
        return (
          <button key={s.id} onClick={() => onJump(s.id)}
            title={`Station ${s.number} · ${s.title}`}
            style={{
              appearance: "none", border: 0, padding: 0, cursor: "pointer",
              width: 22, height: 22, borderRadius: "50%",
              display: "grid", placeItems: "center",
              background: done ? "var(--ink)" : "transparent",
              boxShadow: done ? "none" : "inset 0 0 0 1.5px var(--ink)",
              color: done ? "var(--paper)" : "var(--ink)",
              fontFamily: "var(--f-body)", fontWeight: 700, fontSize: 11,
            }}>
            {done ? "✓" : s.number}
          </button>
        );
      })}
    </div>
  );
}

// ── QuestionCard: shuffleable "pull a question" deck ────────────────────────
function QuestionCard({ questions, accentColor }) {
  // Normalize: accept legacy string[] OR new {q, hint}[].
  const cards = questions.map((x) => typeof x === "string" ? { q: x } : x);

  const [order, setOrder] = useState(() =>
    [...Array(cards.length).keys()].sort(() => Math.random() - 0.5));
  const [i, setI] = useState(0);
  const [revealed, setRevealed] = useState(false);
  const [showHint, setShowHint] = useState(false);
  const total = cards.length;
  const current = revealed ? cards[order[i]] : null;

  function next() {
    if (!revealed) { setRevealed(true); return; }
    setRevealed(false);
    setShowHint(false);
    setTimeout(() => {
      const nextI = (i + 1) % total;
      setI(nextI);
      if (nextI === 0) setOrder([...order].sort(() => Math.random() - 0.5));
      setRevealed(true);
    }, 160);
  }

  return (
    <div className="paper" style={{
      position: "relative", padding: "22px 22px 18px",
      background: "linear-gradient(180deg, #fbf3df 0%, #f0e2bd 100%)",
      borderColor: accentColor, borderWidth: 1.5,
    }}>
      {/* Tape strips */}
      <div aria-hidden="true" style={tapeLeft} />
      <div aria-hidden="true" style={tapeRight} />

      <div style={{ display: "flex", alignItems: "baseline", justifyContent: "space-between", marginBottom: 6 }}>
        <span className="h-eyebrow" style={{ color: accentColor }}>Ask your kid</span>
        <span style={{ fontFamily: "var(--f-body)", fontSize: 11, color: "var(--ink-mute)", fontWeight: 600 }}>
          {revealed ? `${i + 1} / ${total}` : `${total} cards`}
        </span>
      </div>

      <div style={{ minHeight: 96, display: "flex", alignItems: "center" }}>
        {revealed ? (
          <p className="h-display" key={i}
             style={{
               fontSize: "clamp(22px, 4.8vw, 28px)",
               margin: 0, color: "var(--ink)", fontStyle: "italic",
               animation: "qfade 240ms ease",
             }}>
            "{current.q}"
          </p>
        ) : (
          <div style={{ display: "flex", alignItems: "center", gap: 14, animation: "nudge 1.8s ease-in-out infinite" }}>
            <span className="h-hand" style={{ fontSize: 42, color: accentColor }}>
              Tap to draw a card
            </span>
            <span style={{ fontSize: 30 }}>👉</span>
          </div>
        )}
      </div>

      {/* Grown-up hint — collapsible. Kid sees only the question; parent taps for context. */}
      {revealed && current.hint && (
        <div style={{ marginTop: 14, borderTop: "1px dashed var(--rule)", paddingTop: 12 }}>
          <button onClick={() => setShowHint(v => !v)}
            style={{
              appearance: "none", border: 0, background: "transparent",
              cursor: "pointer", padding: 0, display: "flex", alignItems: "center", gap: 8,
              color: accentColor, fontFamily: "var(--f-body)", fontWeight: 600, fontSize: 12,
              letterSpacing: "0.06em", textTransform: "uppercase",
            }}>
            <span style={{
              width: 16, height: 16, borderRadius: "50%", display: "grid", placeItems: "center",
              background: accentColor, color: "var(--paper)", fontSize: 10, fontWeight: 700,
              fontFamily: "var(--f-body)",
            }}>
              {showHint ? "−" : "i"}
            </span>
            <span>{showHint ? "Hide note" : "For the grown-up"}</span>
          </button>
          {showHint && (
            <div style={{
              marginTop: 10, padding: "10px 12px",
              background: "rgba(0,0,0,0.04)", borderRadius: 8,
              animation: "qfade 220ms ease",
            }}>
              <p style={{ margin: 0, fontSize: 14, lineHeight: 1.55, color: "var(--ink-soft)" }}>
                {current.hint}
              </p>
            </div>
          )}
        </div>
      )}

      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginTop: 14 }}>
        <button className="btn btn-ghost" onClick={next}
                style={{ borderColor: accentColor, color: accentColor }}>
          {revealed ? "Pull another →" : "Pull a card"}
        </button>
        {revealed && (
          <button onClick={() => { setRevealed(false); setShowHint(false); }}
                  style={{
                    appearance: "none", border: 0, background: "transparent",
                    cursor: "pointer", color: "var(--ink-mute)", fontSize: 12,
                    fontFamily: "var(--f-body)", fontWeight: 500,
                  }}>
            hide
          </button>
        )}
      </div>

      <style>{`
        @keyframes qfade {
          from { opacity: 0; transform: translateY(6px) rotate(-0.4deg); }
          to   { opacity: 1; transform: translateY(0) rotate(0); }
        }
        @keyframes nudge {
          0%, 100% { transform: translateX(0); }
          50%      { transform: translateX(3px); }
        }
      `}</style>
    </div>
  );
}

const tapeLeft = {
  position: "absolute", top: -8, left: 18, width: 56, height: 18,
  background: "rgba(184,65,43,0.18)", transform: "rotate(-3deg)",
  borderLeft: "1px solid rgba(184,65,43,0.32)",
  borderRight: "1px solid rgba(184,65,43,0.32)",
};
const tapeRight = {
  position: "absolute", top: -8, right: 22, width: 48, height: 18,
  background: "rgba(44,72,112,0.16)", transform: "rotate(2.5deg)",
  borderLeft: "1px solid rgba(44,72,112,0.32)",
  borderRight: "1px solid rgba(44,72,112,0.32)",
};

// ── HelmetDiagram: simple side-profile diagram for the helmet fit station ──
function HelmetDiagram({ accent = "var(--accent)" }) {
  return (
    <svg viewBox="0 0 320 220" width="100%" style={{ maxWidth: 360, display: "block" }} role="img" aria-label="Helmet fit diagram showing two-finger gap above eyebrow and Y-strap below ear">
      <defs>
        <pattern id="stripe" width="6" height="6" patternUnits="userSpaceOnUse" patternTransform="rotate(45)">
          <rect width="6" height="6" fill="var(--paper-2)" />
          <line x1="0" y1="0" x2="0" y2="6" stroke="var(--ink-mute)" strokeWidth="1" opacity="0.25" />
        </pattern>
      </defs>
      {/* Head profile (very simple) */}
      <path d="M 100,160 C 80,160 60,150 56,120 C 50,80 80,52 130,50 C 175,48 205,68 210,100 L 210,140 C 210,160 195,168 175,168 L 168,180 C 165,188 158,194 148,194 L 115,194 C 105,194 100,188 100,180 Z"
            fill="var(--paper)" stroke="var(--ink)" strokeWidth="2" strokeLinejoin="round" />
      {/* Ear */}
      <ellipse cx="150" cy="130" rx="10" ry="14" fill="var(--paper-2)" stroke="var(--ink)" strokeWidth="1.5" />
      {/* Helmet */}
      <path d="M 60,108 C 64,68 100,40 145,40 C 195,40 220,72 220,105 L 220,118 L 60,118 Z"
            fill="url(#stripe)" stroke={accent} strokeWidth="2.5" strokeLinejoin="round" />
      <path d="M 60,118 L 220,118" stroke={accent} strokeWidth="2.5" />
      {/* Front edge marker */}
      <line x1="80" y1="118" x2="80" y2="100" stroke={accent} strokeWidth="2.5" />
      {/* Eye + eyebrow */}
      <line x1="86" y1="90" x2="98" y2="88" stroke="var(--ink)" strokeWidth="2.2" strokeLinecap="round" />
      <circle cx="92" cy="98" r="2.2" fill="var(--ink)" />
      {/* Two-finger gap */}
      <g>
        <line x1="80" y1="98" x2="80" y2="118" stroke="var(--ink)" strokeWidth="1" strokeDasharray="3 2" />
        <text x="68" y="112" textAnchor="end" fontFamily="var(--f-hand)" fontSize="22" fill={accent}>2 fingers</text>
        <path d="M 70,108 Q 76,108 80,108" stroke={accent} strokeWidth="1.5" fill="none" markerEnd="url(#arr)" />
      </g>
      {/* Y strap */}
      <path d="M 150,118 L 150,140 L 145,168 M 150,140 L 155,168"
            stroke={accent} strokeWidth="2" fill="none" />
      {/* Chin strap */}
      <path d="M 148,168 C 140,180 130,182 118,178"
            stroke={accent} strokeWidth="2" fill="none" />
      {/* Labels */}
      <g fontFamily="var(--f-hand)" fontSize="20" fill="var(--ink-soft)">
        <text x="218" y="80" textAnchor="start">level, forward</text>
        <line x1="200" y1="80" x2="215" y2="78" stroke="var(--ink-soft)" strokeWidth="1" />
        <text x="180" y="148">Y under ear</text>
        <line x1="158" y1="142" x2="175" y2="144" stroke="var(--ink-soft)" strokeWidth="1" />
        <text x="108" y="210">1 finger under chin</text>
      </g>
      <defs>
        <marker id="arr" markerWidth="6" markerHeight="6" refX="5" refY="3" orient="auto">
          <path d="M0,0 L6,3 L0,6 Z" fill={accent} />
        </marker>
      </defs>
    </svg>
  );
}

// Export to window so other Babel scripts can use these
Object.assign(window, {
  cls, readLS, writeLS,
  HandUnderline, StationStamp, ProgressDots, QuestionCard, HelmetDiagram,
});
