// Live Quiz — shared data + components used by both host and player.
// Globals out: LIVE_QUESTIONS, LIVE_PLAYERS, avatarColor, Shape, SHAPE_META,
//   CountdownRing, FauxQR, LeaderboardRow, Podium

// Live questions mix MC (lexical choice) with TYPED (word formation / grammar) —
// just like practice. `mode` decides the player input + the reveal shape.
const LIVE_QUESTIONS = [
  { id: "q1", family: "Lexical Choice", mode: "mc",
    prompt: "She made a real ___ to finish the project on time.",
    options: ["effort", "attempt", "trial", "force"], correct: 0 },
  { id: "q2", family: "Word Formation", mode: "typed", base: "POSSIBLE",
    prompt: "It was completely ___ to hear over all the noise.",
    answer: "impossible", alts: [], wrongPool: ["unpossible", "imposible", "impossable", "not possible"] },
  { id: "q3", family: "Grammar", mode: "typed", base: "GO",
    prompt: "By the time we arrived, the train ___ already.",
    answer: "had gone", alts: ["had left"], wrongPool: ["has gone", "went", "had went", "was gone"] },
  { id: "q4", family: "Lexical Choice", mode: "mc",
    prompt: "They finally reached an important ___ after the talks.",
    options: ["agreement", "arrangement", "decision", "promise"], correct: 0 },
];

function lvNorm(s) { return (s || "").trim().toLowerCase().replace(/\s+/g, " "); }
function lvCheck(raw, q) {
  const u = lvNorm(raw);
  if (!u) return false;
  return u === lvNorm(q.answer) || (q.alts || []).some(a => lvNorm(a) === u);
}

// Typed reveal: the 3 most-written answers + an "Others" column. The one that
// matches the correct answer is flagged (rendered green).
function typedDistribution(q, total, youText) {
  const counts = {};
  const add = (label) => {
    const k = lvNorm(label);
    if (!counts[k]) counts[k] = { label, count: 0, correct: k === lvNorm(q.answer) };
    counts[k].count++;
  };
  for (let k = 0; k < total; k++) {
    let h = 0; const key = "t" + q.id + "_" + k;
    for (let j = 0; j < key.length; j++) h = (h * 31 + key.charCodeAt(j)) >>> 0;
    if (h % 100 < 66) add(q.answer);
    else add(q.wrongPool[h % q.wrongPool.length]);
  }
  if (youText) add(youText);
  const entries = Object.values(counts).sort((a, b) => b.count - a.count);
  const cols = entries.slice(0, 3);
  const others = entries.slice(3).reduce((s, e) => s + e.count, 0);
  if (others > 0) cols.push({ label: "Others", count: others, others: true });
  return cols;
}

// Mock roster. "you" is the local player on the phone.
const LIVE_PLAYERS = [
  { id: "you", name: "You", you: true },
  { id: "p1", name: "Dasha" },
  { id: "p2", name: "Mikhail" },
  { id: "p3", name: "Lena" },
  { id: "p4", name: "Artyom" },
  { id: "p5", name: "Sofia" },
  { id: "p6", name: "Pavel" },
];

// deterministic muted avatar hue from a name (stays in our calm range)
function avatarColor(name) {
  let h = 0;
  for (let i = 0; i < name.length; i++) h = (h * 31 + name.charCodeAt(i)) % 360;
  return `oklch(0.62 0.11 ${h})`;
}

// ---- Shapes: triangle / diamond / circle / square (per answer slot) ----
const SHAPE_META = [
  { key: "tri", cls: "lv-shape-tri" },
  { key: "dia", cls: "lv-shape-dia" },
  { key: "cir", cls: "lv-shape-cir" },
  { key: "sqr", cls: "lv-shape-sqr" },
];
function Shape({ i, size = 26 }) {
  const cls = SHAPE_META[i]?.cls || "";
  const s = size, c = "currentColor";
  const body = [
    <path key="t" d="M12 3l9 16H3z" />,
    <path key="d" d="M12 2l10 10-10 10L2 12z" />,
    <circle key="c" cx="12" cy="12" r="9.5" />,
    <rect key="s" x="3.5" y="3.5" width="17" height="17" rx="2.5" />,
  ][i];
  return (
    <span className={cls} style={{ display: "grid", placeItems: "center" }}>
      <svg width={s} height={s} viewBox="0 0 24 24" fill={c} aria-hidden="true">{body}</svg>
    </span>
  );
}

// ---- Countdown ring (host) ----
function CountdownRing({ remaining, total, size = 124 }) {
  const r = (size - 16) / 2;
  const c = 2 * Math.PI * r;
  const frac = Math.max(0, Math.min(1, remaining / total));
  const danger = remaining <= total * 0.25;
  const warn = !danger && remaining <= total * 0.5;
  return (
    <div className={`lv-ring ${danger ? "is-danger" : warn ? "is-warn" : ""}`} style={{ width: size, height: size }}>
      <svg width={size} height={size}>
        <circle className="lv-ring-track" cx={size / 2} cy={size / 2} r={r} fill="none" strokeWidth="9" />
        <circle className="lv-ring-fill" cx={size / 2} cy={size / 2} r={r} fill="none" strokeWidth="9"
          strokeDasharray={c} strokeDashoffset={c * (1 - frac)} />
      </svg>
      <div className="lv-ring-num">{Math.ceil(remaining)}</div>
    </div>
  );
}

// ---- Faux QR (deterministic grid; looks scannable for the mock) ----
function FauxQR({ seed = 7 }) {
  const n = 21;
  let s = seed * 9301 + 49297;
  const rnd = () => { s = (s * 9301 + 49297) % 233280; return s / 233280; };
  const cells = [];
  for (let y = 0; y < n; y++) for (let x = 0; x < n; x++) {
    const finder = (x < 7 && y < 7) || (x >= n - 7 && y < 7) || (x < 7 && y >= n - 7);
    let on;
    if (finder) {
      const lx = x >= n - 7 ? x - (n - 7) : x, ly = y >= n - 7 ? y - (n - 7) : y;
      on = (lx === 0 || lx === 6 || ly === 0 || ly === 6 || (lx >= 2 && lx <= 4 && ly >= 2 && ly <= 4));
    } else on = rnd() > 0.52;
    if (on) cells.push(<rect key={`${x}-${y}`} x={x} y={y} width="1" height="1" />);
  }
  return (
    <div className="lv-qr">
      <svg viewBox={`0 0 ${n} ${n}`}><g fill="#141615">{cells}</g></svg>
    </div>
  );
}

// ---- Leaderboard row ----
function LeaderboardRow({ rank, name, score, delta, you }) {
  return (
    <div className="lv-row" style={you ? { background: "var(--accent-soft)", borderRadius: 10, marginInline: -8, paddingInline: 8 } : null}>
      <span className="lv-rank">{rank}</span>
      <span className="lv-avatar" style={{ background: avatarColor(name) }}>{name.slice(0, 1)}</span>
      <span className="lv-row-name">{name}{you ? " (you)" : ""}</span>
      <span className="lv-row-score">{score.toLocaleString()}{delta ? <span className="lv-row-delta">+{delta}</span> : null}</span>
    </div>
  );
}

// ---- Podium (top 3: order 2-1-3) ----
function Podium({ top3 }) {
  const order = [top3[1], top3[0], top3[2]].filter(Boolean);
  const heights = { 0: 150, 1: 110, 2: 84 };
  return (
    <div className="lv-podium">
      {order.map((p) => {
        const place = top3.indexOf(p) + 1;
        return (
          <div key={p.name} className={`lv-pod p${place}`}>
            <div className="lv-pod-av" style={{ background: avatarColor(p.name), width: place === 1 ? 76 : 60, height: place === 1 ? 76 : 60 }}>{p.name.slice(0, 1)}</div>
            <div className="lv-pod-name">{p.name}{p.you ? " (you)" : ""}</div>
            <div className="lv-pod-score">{p.score.toLocaleString()}</div>
            <div className="lv-pod-stand" style={{ height: heights[place - 1] }}>{place}</div>
          </div>
        );
      })}
    </div>
  );
}

// =====================================================================
// "Live (elevated)" design helpers — folded in from the Claude Design
// "Live - Landing & Setup" handoff. Shared by landing / setup / lobby / join.
// =====================================================================
const LF_SHAPE_COLORS = ["var(--shape-tri)", "var(--shape-dia)", "var(--shape-cir)", "var(--shape-sqr)"];
function LfShape({ i, size = 26, color }) {
  const body = [
    <path key="t" d="M12 3l9 16H3z" />,
    <path key="d" d="M12 2l10 10-10 10L2 12z" />,
    <circle key="c" cx="12" cy="12" r="9.5" />,
    <rect key="s" x="3.5" y="3.5" width="17" height="17" rx="2.5" />,
  ][i];
  return <svg width={size} height={size} viewBox="0 0 24 24" fill={color || LF_SHAPE_COLORS[i]} aria-hidden="true">{body}</svg>;
}
const LF_BG_SHAPES = [
  { i: 0, top: "12%", left: "8%",  size: 120, dur: 34, dx: "60px",  dy: "-40px", dr: "60deg" },
  { i: 1, top: "62%", left: "14%", size: 88,  dur: 41, dx: "-50px", dy: "30px",  dr: "-80deg" },
  { i: 2, top: "20%", left: "82%", size: 150, dur: 47, dx: "-40px", dy: "50px",  dr: "70deg" },
  { i: 3, top: "70%", left: "78%", size: 104, dur: 38, dx: "50px",  dy: "-30px", dr: "-60deg" },
  { i: 1, top: "42%", left: "48%", size: 64,  dur: 52, dx: "30px",  dy: "40px",  dr: "100deg" },
  { i: 3, top: "86%", left: "40%", size: 76,  dur: 44, dx: "-40px", dy: "-50px", dr: "50deg" },
];
function LiveBackgroundField() {
  return (
    <div className="lf-bg" aria-hidden="true">
      {LF_BG_SHAPES.map((s, k) => (
        <div key={k} className={`lf-bg-shape s${s.i}`}
          style={{ top: s.top, left: s.left, animationDuration: `${s.dur}s`, animationDelay: `${-k * 4}s`, "--dx": s.dx, "--dy": s.dy, "--dr": s.dr }}>
          <LfShape i={s.i} size={s.size} color="currentColor" />
        </div>
      ))}
    </div>
  );
}
function LiveBrand() {
  return (
    <span className="lf-brand">
      <span className="mk">iri<span className="a">kos</span></span>
      <span className="live"><span className="lf-live-dot" />LIVE</span>
    </span>
  );
}
function LfCheck() {
  return <span className="lf-check"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="3.4" strokeLinecap="round" strokeLinejoin="round"><path d="m5 12 5 5 9-11" /></svg></span>;
}
function LfArrow({ size = 19 }) {
  return <svg width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><path d="M5 12h13M13 6l6 6-6 6" /></svg>;
}
function LiveCountUp({ value }) {
  const [shown, setShown] = React.useState(value);
  const ref = React.useRef(value);
  React.useEffect(() => {
    const from = ref.current, to = value;
    if (from === to) return;
    const start = (window.performance && performance.now()) || Date.now(), dur = 460;
    let raf;
    const tick = (now) => {
      const t = Math.min(1, (now - start) / dur);
      const eased = 1 - Math.pow(1 - t, 3);
      setShown(Math.round(from + (to - from) * eased));
      if (t < 1) raf = requestAnimationFrame(tick); else ref.current = to;
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, [value]);
  return <b>{shown.toLocaleString()}</b>;
}
// Shared dark stage: drifting shape field + centered scroll area.
function LiveFunStage({ children, className }) {
  return (
    <div className={`lf lf-screen-stage ${className || ""}`}>
      <LiveBackgroundField />
      <div className="lf-scroll">{children}</div>
    </div>
  );
}

Object.assign(window, { LIVE_QUESTIONS, LIVE_PLAYERS, avatarColor, Shape, SHAPE_META, CountdownRing, FauxQR, LeaderboardRow, Podium, lvNorm, lvCheck, typedDistribution,
  LfShape, LiveBackgroundField, LiveBrand, LfCheck, LfArrow, LiveCountUp, LiveFunStage });
