/* Language Partner — screens: Dashboard, Language page, Egyptian corner, Burnzee. Exported to window. */
const { useState: useStateS, useEffect: useEffectS, useRef: useRefS } = React;

/* ---------- DASHBOARD ---------- */
function Dashboard({ languages, onOpen, onAdd, onBurnzee }) {
  const { minutes, goal, pct } = useDailyTime();
  useBank("zh"); // subscribe so counts refresh live while on the dashboard
  const stats = languages.map((l) => window.LPBank.counts(l.id));
  const totalActive = stats.reduce((n, c) => n + c.learning, 0);
  const now = new Date();
  const dateline = now.toLocaleDateString(undefined, { weekday: "long", day: "numeric", month: "long" });
  const hour = now.getHours();
  const greeting = hour < 12 ? "Good morning." : hour < 18 ? "Good afternoon." : "Good evening.";
  return (
    <div className="screen dash">
      <header className="dash-head">
        <div className="dash-greet">
          <div className="overline">{dateline}</div>
          <h1 className="dash-title">{greeting}</h1>
          <p className="dash-sub">Two languages, steady and slow. <button className="link-helen" onClick={onBurnzee}>Ask Burnzee</button> what's next.</p>
        </div>
      </header>

      <div className="today-card">
        <div className="today-ring" style={{ "--pct": pct + "%" }}>
          <div className="today-ring-inner"><b>{minutes}</b><span>/ {goal} min</span></div>
        </div>
        <div className="today-meta">
          <div className="today-line"><span className="overline">Today's practice</span></div>
          <div className="today-stat"><b>{totalActive}</b> words &amp; characters in active rotation</div>
          <div className="today-hint">{minutes >= goal ? "You've hit today's goal — anything more is a bonus." : "About 5 minutes each — your subconscious does the rest between sessions."}</div>
        </div>
      </div>

      <div className="overline sec-divider">Your languages</div>
      <div className="lang-grid">
        {languages.map((l, i) => {
          const c = stats[i];
          return (
          <button key={l.id} className="lang-card" onClick={() => onOpen(l.id)} style={{ "--accent": l.accent }}>
            <div className="lc-top">
              <div className="lc-native" data-lang={l.id}>{l.native}</div>
              <div className="lc-due">{c.learning ? <span className="due-pip">{c.learning} active</span> : <span className="due-rest">rested</span>}</div>
            </div>
            <div className="lc-name">{l.name}</div>
            <div className="lc-theme">{l.theme}</div>
            <div className="lc-foot">
              <span className="lc-known">{c.known} known</span>
              <span className="lc-dot">·</span>
              <span className="lc-level">{c.total} / {c.goal}</span>
            </div>
          </button>);
        })}
        <button className="lang-card add-card" onClick={onAdd}>
          <div className="add-plus"><Icon name="plus" size={26} /></div>
          <div className="add-text">Add a language</div>
          <div className="add-sub">Latin, Greek, Japanese, Nahuatl…</div>
        </button>
      </div>
    </div>);

}

/* ---------- LANGUAGE PAGE ---------- */
const SECTION_META = {
  learn: { label: "Learn", icon: "spark" },
  refresh: { label: "Refresh", icon: "refresh" },
  translate: { label: "Translate", icon: "feather" },
  grammar: { label: "Grammar", icon: "book" },
  conjugate: { label: "Conjugate", icon: "swap" },
  read: { label: "Read", icon: "eye" },
  words: { label: "Words", icon: "book" },
  glyphs: { label: "Decipher", icon: "eye" }
};

function LanguagePage({ lang, onBurnzee, onSection }) {
  const [tab, setTab] = useStateS(lang.sections[0]);
  const bodyRef = useRefS(null);
  const accent = lang.accent;
  const nlen = (lang.native || "").length;
  const nsize = nlen <= 3 ? 64 : nlen <= 8 ? 50 : nlen <= 11 ? 40 : 32;

  useEffectS(() => {if (bodyRef.current) bodyRef.current.scrollTop = 0;}, [tab]);
  useEffectS(() => {if (onSection) onSection(tab);}, [tab]);

  return (
    <div className="screen langpage" style={{ "--accent": accent }}>
      <div className="lp-hero">
        <div className="lp-hero-native" data-lang={lang.id} style={{ fontSize: nsize }}>{lang.native}</div>
        <div className="lp-hero-meta">
          <div className="overline" style={{ color: accent }}>{lang.theme}</div>
          <h1 className="lp-hero-name">{lang.name}</h1>
          <p className="lp-hero-note">{lang.note}</p>
        </div>
      </div>

      <div className="seg-wrap">
        <div className="seg">
          {lang.sections.map((s) =>
          <button key={s} className={"seg-btn" + (tab === s ? " on" : "")}
          style={tab === s ? { color: accent, borderColor: accent } : null}
          onClick={() => setTab(s)}>
              {SECTION_META[s].label}
            </button>
          )}
        </div>
      </div>

      <div className="lp-body" ref={bodyRef}>
        {tab === "learn" && <LearnSection lang={lang} accent={accent} onBurnzee={onBurnzee} />}
        {tab === "refresh" && <RefreshSection lang={lang} accent={accent} />}
        {tab === "translate" && <TranslateSection lang={lang} accent={accent} />}
        {tab === "grammar" && <GrammarSection lang={lang} accent={accent} />}
        {tab === "conjugate" && <ConjugateSection lang={lang} accent={accent} />}
        {tab === "read" && <ReadSection lang={lang} accent={accent} />}
        {tab === "words" && <WordsSection lang={lang} accent={accent} />}
        {tab === "glyphs" && <GlyphSection lang={lang} accent={accent} onBurnzee={onBurnzee} />}
      </div>
    </div>);

}

function LearnSection({ lang, accent, onBurnzee }) {
  const isLetters = lang.learnKind === "letters";
  const { words } = useBank(lang.id);
  const [round, bump] = useRound();
  const batch = isLetters ? 4 : lang.id === "zh" ? 4 : 3;
  const bankLearning = words.filter((w) => w.status !== "known").slice().reverse();
  const pool = [...bankLearning, ...lang.learn];
  const shown = rotate(pool, round, batch);
  const more = pool.length > batch;

  // idiom — rotates daily; Burnzee can offer a fresh one for trusted languages
  const reliable = window.LPBank.AI_RELIABLE[lang.id];
  const connected = window.LPApi && window.LPApi.isConfigured();
  const [freshIdiom, setFreshIdiom] = useStateS(null);
  const [idiomBusy, setIdiomBusy] = useStateS(false);
  const idiom = freshIdiom || dailyIdiom(lang);
  async function newIdiom() {
    if (idiomBusy) return;
    setIdiomBusy(true);
    try { const i = await window.LPBank.makeIdiom(lang); setFreshIdiom(i); } catch (e) {} finally { setIdiomBusy(false); }
  }

  return (
    <section className="lp-sec">
      <div className="sec-head-row">
        <SectionHead label="Learn" accent={accent}
        title={isLetters ? "New letters today" : "New words today"}
        sub={isLetters ? "Shapes to recognize by sight and by sound." : "A small set, tied to today's theme. Read each aloud."} />
        {more ? <RefreshTab accent={accent} onClick={bump} label="New set" /> : null}
      </div>

      <BuildVocab lang={lang} accent={accent} onGenerated={bump} />

      <div className="learn-grid">
        {shown.map((item) =>
        <VocabCard key={item.id} item={item} langId={lang.id} accent={accent} kind={lang.learnKind} />
        )}
      </div>
      {idiom ?
      <div className="idiom" style={{ borderColor: accent }}>
          <div className="idiom-head">
            <div className="overline" style={{ color: accent }}>Idiom of the day</div>
            {reliable && connected ?
            <button className="idiom-new" onClick={newIdiom} disabled={idiomBusy} style={{ color: accent }}>
                <Icon name="refresh" size={15} /> {idiomBusy ? "asking…" : "New from Burnzee"}
              </button> : null}
          </div>
          <div className="idiom-glyph" data-lang={lang.id}>{idiom.glyph}</div>
          {idiom.roman ? <div className="idiom-roman" style={{ color: accent }}>{idiom.roman}</div> : null}
          <div className="idiom-gloss">{idiom.gloss}</div>
          {idiom.note ? <div className="idiom-note">{idiom.note}</div> : null}
          {idiom.source === "ai" ? <div className="idiom-flag">Burnzee's suggestion — worth a quick double-check.</div> : null}
        </div> :
      null}
      <button className="helen-inline" onClick={onBurnzee} style={{ borderColor: accent }}>
        <span className="hi-dot" style={{ background: accent }} />
        Ask Burnzee why these words, today
      </button>
    </section>);

}

function RefreshSection({ lang, accent }) {
  const { words } = useBank(lang.id);
  const [round, bump] = useRound();
  const batch = lang.id === "zh" ? 6 : 4;
  // today's new words eligible to fold into rotation: seed learn + bank still-learning
  const graduates = [...lang.learn, ...words.filter((w) => w.status !== "known")]
    .map((l) => ({ id: "r-" + l.id, glyph: l.glyph, roman: l.roman, gloss: l.gloss }));
  // the review pool: seed refresh + everything in the bank
  const refreshPool = [...lang.refresh, ...words.slice().reverse().map((w) => ({ id: w.id, glyph: w.glyph, roman: w.roman, gloss: w.gloss }))];
  const base = rotate(refreshPool, round, batch);
  const [deck, setDeck] = useStateS(base.map((d) => ({ ...d, fresh: false })));
  const [added, setAdded] = useStateS([]);
  // when the round changes (New set / Burnzee re-teach) or the bank grows, pull a fresh slice
  useEffectS(() => {
    setDeck(rotate(refreshPool, round, batch).map((d) => ({ ...d, fresh: false })));
    setAdded([]);
  }, [round, lang.id, refreshPool.length]);
  const remaining = graduates.filter((g) => !added.includes(g.id));
  function addMore() {
    const slot = remaining.slice(0, 2);
    if (!slot.length) return;
    setAdded((a) => [...a, ...slot.map((b) => b.id)]);
    setDeck((d) => [...slot.map((b) => ({ ...b, fresh: true })), ...d.map((c) => ({ ...c, fresh: false }))]);
  }
  return (
    <section className="lp-sec">
      <div className="sec-head-row">
        <SectionHead label="Refresh" accent={accent} title="Seen before — does it stick?"
        sub="Tap each card to reveal. Recall it easily and it returns less often; let it slip and it comes back sooner." />
        {refreshPool.length > batch ? <RefreshTab accent={accent} onClick={bump} label="New set" /> : null}
      </div>
      <div className="refresh-bar">
        <button className="refresh-btn" onClick={addMore} disabled={!remaining.length}
        style={{ borderColor: accent, color: remaining.length ? accent : "var(--paper-fade)" }}>
          <Icon name="refresh" size={18} />
          {remaining.length ? `Add ${Math.min(2, remaining.length)} of today's new word${remaining.length > 1 ? "s" : ""}` : "Today's new words are all in rotation"}
        </button>
        <span className="refresh-count">{deck.length} cards in your deck</span>
      </div>
      <div className="flip-grid">
        {deck.map((item) => <FlipCard key={item.id} item={item} langId={lang.id} accent={accent} fresh={item.fresh} />)}
      </div>
    </section>);

}

function TranslateSection({ lang, accent }) {
  useBank(lang.id);
  const batch = 2;
  const bankT = window.LPBank.translates(lang.id);
  const pool = [...bankT, ...(lang.translate || [])];
  const [idx, setIdx] = useStateS(0);
  const connected = window.LPApi && window.LPApi.isConfigured();
  const [busy, setBusy] = useStateS(false);
  const [err, setErr] = useStateS(null);
  useEffectS(() => LPBus.on(() => setIdx((i) => pool.length ? (i + batch) % pool.length : 0)), [pool.length]);
  const shown = [];
  for (let i = 0; i < Math.min(batch, pool.length); i++) shown.push(pool[(idx + i) % pool.length]);
  async function gen() {
    if (busy) return; setBusy(true); setErr(null);
    try { await window.LPBank.makeTranslate(lang, 3); setIdx(0); }
    catch (e) { setErr(e.message || "Couldn't build drills."); } finally { setBusy(false); }
  }
  return (
    <section className="lp-sec">
      <div className="sec-head-row">
        <SectionHead label="Translate" accent={accent} title="Put the pieces together"
        sub="Build the sentence from today's words and the ones you already know." />
        {pool.length > batch ? <RefreshTab accent={accent} onClick={() => setIdx((i) => (i + batch) % pool.length)} label="New set" /> : null}
      </div>
      {connected ?
      <button className="gen-btn" onClick={gen} disabled={busy} style={{ borderColor: accent, color: accent }}>
          <Icon name="feather" size={17} /> {busy ? "Burnzee is writing drills…" : "Build new drills from your words"}
        </button> : null}
      {err ? <div className="gen-err">{err}</div> : null}
      <div className="translate-stack">
        {shown.length ? shown.map((t, i) => <ChipBuilder key={idx + "-" + i + "-" + t.prompt} item={t} langId={lang.id} accent={accent} />) :
        <div className="gen-empty">Add some words, then Burnzee can turn them into translation drills.</div>}
      </div>
    </section>);

}

function GrammarSection({ lang, accent }) {
  const [round, bump] = useRound();
  const items = lang.grammar;
  const start = items.length ? round % items.length : 0;
  const ordered = [...items.slice(start), ...items.slice(0, start)].map((g, i) => ({ ...g, isNew: i === 0 }));
  return (
    <section className="lp-sec">
      <div className="sec-head-row">
        <SectionHead label="Grammar" accent={accent} title="One idea at a time"
        sub="The featured concept sits on top. Expand the rest to revisit what came before." />
        {items.length > 1 ? <RefreshTab accent={accent} onClick={bump} label="Next concept" /> : null}
      </div>
      <GrammarStack key={round} items={ordered} langId={lang.id} accent={accent} />
    </section>);

}

function ConjCell({ f, langId, accent, test }) {
  const [shown, setShown] = useStateS(false);
  const reveal = !test || shown;
  return (
    <button className={"conj-cell" + (test ? " testable" : "") + (reveal && test ? " revealed" : "")}
    onClick={() => test && setShown((s) => !s)} style={reveal && test ? { borderColor: accent } : null}>
      <span className="conj-pron">{f.p}</span>
      {reveal ?
      <span className="conj-form" data-lang={langId} style={test ? { color: accent } : null}>{f.f}</span> :
      <span className="conj-tap">tap</span>}
    </button>);

}

const CONJ_TENSES = {
  fr: ["Présent", "Passé composé", "Imparfait", "Futur simple", "Conditionnel", "Subjonctif"],
  es: ["Presente", "Pretérito", "Imperfecto", "Futuro", "Condicional", "Subjuntivo"]
};

function ConjugateSection({ lang, accent }) {
  useBank(lang.id); // re-render when a generated table lands in the bank
  const verbs = lang.conjugate || [];
  const [vi, setVi] = useStateS(0);
  const [round] = useRound();
  const connected = window.LPApi && window.LPApi.isConfigured();
  const verb = verbs[vi];
  const tenses = CONJ_TENSES[lang.id] || (verb ? [verb.tense] : []);
  const [tense, setTense] = useStateS(verb ? verb.tense : "");
  const [test, setTest] = useStateS(false);
  const [reveal, setReveal] = useStateS(false);
  const [attempt, setAttempt] = useStateS(0);
  const [busy, setBusy] = useStateS(false);
  const [err, setErr] = useStateS(null);

  // Burnzee re-teach advances the verb
  useEffectS(() => { if (round === 0) return; setVi((v) => (v + 1) % Math.max(1, verbs.length)); }, [round]);
  // changing verb resets to that verb's native tense
  useEffectS(() => { if (verb) setTense(verb.tense); }, [vi, lang.id]);
  // changing verb/tense exits any active test
  useEffectS(() => { setTest(false); setReveal(false); setAttempt((a) => a + 1); }, [vi, tense, lang.id]);

  const seedTable = verb && tense === verb.tense ? verb : null;
  const cached = verb ? window.LPBank.conjGet(lang.id, verb.verb, tense) : null;
  const table = seedTable || cached;

  // auto-generate a missing tense when Burnzee is connected
  useEffectS(() => {
    if (!verb || table || busy || !connected) return;
    let cancel = false;
    setBusy(true); setErr(null);
    window.LPBank.makeConjugation(lang, verb.verb, verb.gloss, tense).
    catch((e) => { if (!cancel) setErr(e.message || "Couldn't build that tense."); }).
    finally(() => { if (!cancel) setBusy(false); });
    return () => { cancel = true; };
  }, [verb && verb.verb, tense, connected, attempt]);

  if (!verb) return null;

  return (
    <section className="lp-sec">
      <div className="sec-head-row">
        <SectionHead label="Conjugate" accent={accent} title="Drill the verb forms"
        sub="Pick a verb and a tense, then test yourself — type each form. Spelling counts; accents don't." />
        {verbs.length > 1 ? <RefreshTab accent={accent} onClick={() => setVi((v) => (v + 1) % verbs.length)} label="Next verb" /> : null}
      </div>

      <div className="verb-chips">
        {verbs.map((v, i) =>
        <button key={v.verb} className={"verb-chip" + (i === vi ? " on" : "")} data-lang={lang.id}
        style={i === vi ? { borderColor: accent, color: accent } : null}
        onClick={() => setVi(i)}>{v.verb}</button>
        )}
      </div>

      {tenses.length > 1 ?
      <div className="tense-row">
          {tenses.map((t) =>
        <button key={t} className={"tense-pick" + (t === tense ? " on" : "")}
        style={t === tense ? { borderColor: accent, color: accent } : null}
        onClick={() => setTense(t)}>{t}</button>
        )}
        </div> : null}

      <div className="conj-card">
        <div className="conj-head">
          <div>
            <div className="conj-verb" data-lang={lang.id}>{verb.verb}</div>
            <div className="conj-gloss">{verb.gloss}</div>
          </div>
          <div className="conj-tense" style={{ color: accent }}>{tense}</div>
        </div>

        {busy ?
        <div className="conj-loading">Burnzee is conjugating <b>{verb.verb}</b> in the {tense}…</div> :
        err ?
        <div className="conj-loading">{err} <button className="puzzle-next" onClick={() => setAttempt((a) => a + 1)} style={{ color: accent }}>Try again</button></div> :
        !table ?
        <div className="conj-loading">Connect Burnzee in Settings to see other tenses.</div> :

        <>
            <div className="conj-grid">
              {table.forms.map((f, i) =>
            test ?
            <ConjInputCell key={verb.verb + tense + attempt + i} form={f} langId={lang.id} accent={accent} reveal={reveal} attempt={attempt} /> :
            <ConjCell key={verb.verb + "-false-" + i} f={f} langId={lang.id} accent={accent} test={false} />
            )}
            </div>
            {table.pattern ? <div className="conj-pattern" style={{ borderColor: accent }}>{table.pattern}</div> : null}
            {!test ?
          <button className="refresh-btn" onClick={() => { setTest(true); setReveal(false); setAttempt((a) => a + 1); }}
          style={{ borderColor: accent, color: accent, marginTop: "4px" }}>
                <Icon name="swap" size={18} /> Test me — type the forms
              </button> :

          <div className="conj-test-row">
                {!reveal ?
            <button className="btn-ghost" onClick={() => setReveal(true)} style={{ borderColor: accent, color: accent }}>Check answers</button> :
            <button className="btn-ghost" onClick={() => { setReveal(false); setAttempt((a) => a + 1); }} style={{ borderColor: accent, color: accent }}>Try again</button>}
                <button className="btn-text" onClick={() => { setTest(false); setReveal(false); }}>Show the forms</button>
              </div>}
          </>}
      </div>
    </section>);

}

function ReadSection({ lang, accent }) {
  useBank(lang.id);
  const bankReads = window.LPBank.reads(lang.id);
  const pool = [...bankReads, lang.read, ...(lang.readsMore || [])].filter(Boolean);
  const [idx, setIdx] = useStateS(0);
  const connected = window.LPApi && window.LPApi.isConfigured();
  const [busy, setBusy] = useStateS(false);
  const [err, setErr] = useStateS(null);
  useEffectS(() => LPBus.on(() => setIdx((i) => pool.length ? (i + 1) % pool.length : 0)), [pool.length]);
  async function gen() {
    if (busy) return; setBusy(true); setErr(null);
    try { await window.LPBank.makeReading(lang); setIdx(0); }
    catch (e) { setErr(e.message || "Couldn't weave a passage."); } finally { setBusy(false); }
  }
  const passage = pool.length ? pool[idx % pool.length] : null;
  return (
    <section className="lp-sec">
      <div className="sec-head-row">
        <SectionHead label="Read" accent={accent} title={passage ? passage.title : "Read"} sub={passage ? passage.subtitle : ""} />
        {pool.length > 1 ? <RefreshTab accent={accent} onClick={() => setIdx((i) => (i + 1) % pool.length)} label="New passage" /> : null}
      </div>
      <p className="read-intro">This is the point of it all — words you've met, woven into something to read. Tap any word you're unsure of.</p>
      {connected ?
      <button className="gen-btn" onClick={gen} disabled={busy} style={{ borderColor: accent, color: accent }}>
          <Icon name="feather" size={17} /> {busy ? "Burnzee is weaving…" : "Weave a new passage from your words"}
        </button> : null}
      {err ? <div className="gen-err">{err}</div> : null}
      {passage ?
      <GlossReader key={idx + "-" + (passage.title || "")} read={passage} langId={lang.id} accent={accent} /> :
      <div className="gen-empty">Add some words, then Burnzee can weave them into a passage to read.</div>}
    </section>);

}

/* ---------- EGYPTIAN: decipher for fun ---------- */
function shuffle(arr) {
  const a = arr.slice();
  for (let i = a.length - 1; i > 0; i--) {const j = Math.floor(Math.random() * (i + 1));[a[i], a[j]] = [a[j], a[i]];}
  return a;
}
function GlyphSection({ lang, accent, onBurnzee }) {
  const [choice, setChoice] = useStateS(null);
  const [pIdx, setPIdx] = useStateS(0);
  const [glyphOrder, setGlyphOrder] = useStateS(() => lang.glyphs.slice(0, 4));
  const pz = lang.puzzles[pIdx];
  function refresh() {
    setChoice(null);
    setPIdx((i) => (i + 1) % lang.puzzles.length);
    setGlyphOrder(shuffle(lang.glyphs).slice(0, 4));
  }
  return (
    <section className="lp-sec">
      <div className="sec-head-row">
        <SectionHead label="Decipher" accent={accent} title="Sound out the signs"
        sub="No drills here. Read each line, guess the sense, then check yourself." />
        <button className="refresh-btn compact" onClick={refresh} style={{ borderColor: accent, color: accent }}>
          <Icon name="refresh" size={18} /> New glyphs
        </button>
      </div>
      <div className="glyph-grid">
        {glyphOrder.map((g) =>
        <div key={g.translit} className="glyph-card">
            <div className="glyph-line" data-lang="egy">{g.line}</div>
            <div className="glyph-translit" style={{ color: accent }}>{g.translit}</div>
            <div className="glyph-gloss">{g.gloss}</div>
            <div className="glyph-hint">{g.hint}</div>
          </div>
        )}
      </div>
      <div className="puzzle" style={{ borderColor: accent }}>
        <div className="puzzle-head">
          <div className="overline" style={{ color: accent }}>Try a line · {pIdx + 1} of {lang.puzzles.length}</div>
        </div>
        <div className="puzzle-line" data-lang="egy">{pz.line}</div>
        <div className="puzzle-translit">{pz.translit}</div>
        <div className="puzzle-opts">
          {pz.options.map((o, i) => {
            const picked = choice === i;
            const reveal = choice !== null;
            const right = i === pz.answer;
            return (
              <button key={i} className={"puzzle-opt" + (reveal && right ? " right" : "") + (picked && !right ? " wrong" : "")}
              onClick={() => setChoice(i)} disabled={reveal}>{o}</button>);

          })}
        </div>
        {choice !== null ?
        <div className="puzzle-note">{choice === pz.answer ? "Yes — " : "Not quite — "}{pz.note}
            <button className="puzzle-next" onClick={refresh} style={{ color: accent }}>Next line →</button>
          </div> :
        null}
      </div>
    </section>);

}

/* ---------- WORDS: the running glossary of everything learned ---------- */
function WordsSection({ lang, accent }) {
  const isLetters = lang.learnKind === "letters";
  const noun = isLetters ? "letters" : "words";
  const { words } = useBank(lang.id);
  // bank words carry their real status; seed words keep their original bucket
  const seedLearning = (lang.learn || []).map((w) => ({ ...w, status: "learning", seed: true }));
  const seedKnown = (lang.refresh || []).map((w) => ({ ...w, status: "known", seed: true }));
  const bankRows = words.slice().reverse().map((w) => ({ ...w, seed: false }));
  const all = [...bankRows, ...seedLearning, ...seedKnown];

  const [q, setQ] = useStateS("");
  const [filter, setFilter] = useStateS("all"); // all | learning | known
  const [sort, setSort] = useStateS("recent"); // recent | az
  const [round, bump] = useRound();

  let rows = all.filter((w) => filter === "all" || w.status === filter);
  if (q.trim()) {
    const needle = q.trim().toLowerCase();
    rows = rows.filter((w) =>
    (w.glyph || "").toLowerCase().includes(needle) ||
    (w.roman || "").toLowerCase().includes(needle) ||
    (w.gloss || "").toLowerCase().includes(needle));
  }
  if (sort === "az") rows = rows.slice().sort((a, b) => (a.roman || a.glyph).localeCompare(b.roman || b.glyph));else
  if (round > 0) rows = seededShuffle(rows, round); // "Shuffle" reorders the recent view

  const counts = { all: all.length, learning: all.filter((w) => w.status === "learning").length, known: all.filter((w) => w.status === "known").length };

  return (
    <section className="lp-sec">
      <div className="sec-head-row">
        <SectionHead label="Words" accent={accent} title={"Everything you've learned"}
        sub={`Your running glossary — ${all.length} ${noun} so far. Search, filter, and revisit any of them.`} />
        {sort === "recent" ? <RefreshTab accent={accent} onClick={bump} label="Shuffle" /> : null}
      </div>

      <div className="words-search">
        <Icon name="book" size={18} />
        <input className="words-input" value={q} onChange={(e) => setQ(e.target.value)}
        placeholder={`Search ${noun} or meanings…`} />
        {q ? <button className="words-clear" onClick={() => setQ("")}>clear</button> : null}
      </div>

      <div className="words-controls">
        <div className="words-filters">
          {["all", "learning", "known"].map((f) =>
          <button key={f} className={"words-pill" + (filter === f ? " on" : "")}
          style={filter === f ? { borderColor: accent, color: accent } : null}
          onClick={() => setFilter(f)}>
              {f === "all" ? "All" : f === "learning" ? "Learning" : "Known"}
              <span className="words-pill-n">{counts[f]}</span>
            </button>
          )}
        </div>
        <button className="words-sort" onClick={() => setSort((s) => s === "recent" ? "az" : "recent")}>
          <Icon name="swap" size={16} /> {sort === "recent" ? "Recent" : "A–Z"}
        </button>
      </div>

      <div className="words-list">
        {rows.length === 0 ?
        <div className="words-empty">No {noun} match “{q}”.</div> :
        rows.map((w) => {
          const gl = w.glyph || "";
          const gsize = lang.id === "zh" || isLetters ? 30 : gl.length <= 8 ? 24 : gl.length <= 14 ? 20 : 17;
          const toggle = () => { if (!w.seed) window.LPBank.setStatus(lang.id, w.id, w.status === "known" ? "learning" : "known"); };
          return (
            <div className="word-row" key={w.id}>
            <div className="word-glyph" data-lang={lang.id} style={{ fontSize: gsize }}>{w.glyph}</div>
            <div className="word-mid">
              {w.roman ? <div className="word-roman" style={{ color: accent }}>{w.roman}</div> : null}
              <div className="word-gloss">{w.gloss}</div>
            </div>
            <div className="word-right">
              <button className={"word-status " + w.status + (w.seed ? " seedlock" : "")}
                disabled={w.seed} onClick={toggle} title={w.seed ? "" : "Tap to mark " + (w.status === "known" ? "learning" : "known")}
                style={w.status === "learning" ? { color: accent, borderColor: accent } : null}>
                {w.status === "learning" ? "learning" : "known"}
              </button>
              {w.source === "user" ? <button className="word-del" onClick={() => window.LPBank.remove(lang.id, w.id)} title="Remove" aria-label="Remove">✕</button> : null}
              <SpeakButton text={w.ex || w.glyph} langId={lang.id} accent={accent} />
            </div>
          </div>);

        })}
      </div>
    </section>);

}

/* ---------- HELEN ---------- */
function helenSystemPrompt(lang, secLabel) {
  const base =
  "You are Burnzee, a warm, patient, encouraging language guide inside an app called Language Partner. " +
  "The learner's overarching goal is to READ the language; speaking is a welcome bonus, not the focus. " +
  "They learn by repetition with gentle variance and believe in slowly ingraining a vocabulary base to build on. " +
  "Keep replies short and concrete — usually 2 to 4 sentences. When you teach a word or sentence, give the script, " +
  "a simple pronunciation, and the meaning. Never overwhelm; favour one clear idea at a time. Be encouraging and unhurried.";
  if (!lang) return base + " The learner is choosing among several languages.";
  let extra = ` Right now the learner is studying ${lang.name} (${lang.native}). Theme: ${lang.theme}. Their level: ${lang.level}.`;
  if (secLabel) extra += ` They are on the "${secLabel}" section, so orient your help there.`;
  if (lang.id === "zh") extra += " Use Traditional characters (as used in Taiwan) and Hanyu Pinyin with tone marks.";
  if (lang.id === "hi") extra += " Use Devanagari with a simple transliteration.";
  if (lang.id === "egy") extra += " This is Ancient Egyptian for fun — focus on reading short hieroglyphic lines.";
  return base + extra;
}

function BurnzeePanel({ open, onClose, lang, activeSection, onOpenSettings }) {
  const accent = lang && lang.accent || "var(--gold)";
  const secLabel = activeSection && SECTION_META[activeSection] ? SECTION_META[activeSection].label : null;
  const canReteach = !!lang && !!secLabel && secLabel !== "Words";
  const connected = window.LPApi && window.LPApi.isConfigured();
  function reteach() {LPBus.emit();onClose();}

  // ----- scripted intro (used as fallback AND as Burnzee's first chat bubble) -----
  const scriptLines = lang && lang.helen || [
  "I'm Burnzee — your guide for Mandarin and Spanish. I remember where you've been and nudge what's worth revisiting.",
  "Open any language and I'll greet you with what we covered last time."];


  // ----- live chat state -----
  const storeKey = "lp_helen_" + (lang ? lang.id : "home");
  const [msgs, setMsgs] = useStateS([]);
  const [input, setInput] = useStateS("");
  const [busy, setBusy] = useStateS(false);
  const [shown, setShown] = useStateS(1); // for scripted fallback
  const scrollRef = useRefS(null);

  useEffectS(() => {
    if (!open) return;
    setShown(1);
    if (connected) {
      let saved = null;
      try {saved = JSON.parse(localStorage.getItem(storeKey) || "null");} catch (e) {}
      if (saved && saved.length) setMsgs(saved);else
      setMsgs([{ role: "assistant", content: scriptLines[0] }]);
    }
  }, [open, storeKey]);

  useEffectS(() => {
    if (scrollRef.current) scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
  }, [msgs, busy]);

  function persist(next) {try {localStorage.setItem(storeKey, JSON.stringify(next.slice(-30)));} catch (e) {}}

  async function send(text) {
    const content = (text != null ? text : input).trim();
    if (!content || busy) return;
    const next = [...msgs, { role: "user", content }];
    setMsgs(next);setInput("");setBusy(true);
    try {
      const system = { role: "system", content: helenSystemPrompt(lang, secLabel) };
      const reply = await window.LPApi.chat([system, ...next.map((m) => ({ role: m.role, content: m.content }))]);
      const done = [...next, { role: "assistant", content: reply || "…" }];
      setMsgs(done);persist(done);
    } catch (e) {
      setMsgs([...next, { role: "assistant", content: "⚠︎ " + (e.message || "Something went wrong reaching the AI.") }]);
    } finally {setBusy(false);}
  }

  const suggestions = lang ? [
  secLabel === "Grammar" ? "Explain the newest concept simply" : "Quiz me on today's words",
  "Give me one short sentence to read",
  "Why these words today?"] :
  ["What should I study first?", "How does this app work?"];

  return (
    <>
      <div className={"helen-scrim" + (open ? " on" : "")} onClick={onClose} />
      <aside className={"helen-panel" + (open ? " on" : "")} aria-hidden={!open}>
        <div className="helen-head">
          <img className="helen-portrait" src="assets/burnzee-avatar.png" alt="Burnzee" />
          <div className="helen-id">
            <div className="helen-name">Burnzee</div>
            <div className="helen-role" style={{ color: accent }}>{lang ? lang.name + " guide" : "Your guide"}</div>
          </div>
          <button className="iconbtn helen-x" onClick={onClose}>✕</button>
        </div>

        {connected ? (
        /* ===== LIVE CHAT ===== */
        <div className="helen-chat">
            <div className="helen-msgs" ref={scrollRef}>
              {msgs.map((m, i) =>
            <div key={i} className={"hmsg " + (m.role === "user" ? "hmsg-user" : "hmsg-helen")}>
                  {m.role !== "user" ? <span className="helen-tick" style={{ background: accent }} /> : null}
                  {m.content}
                </div>
            )}
              {busy ? <div className="hmsg hmsg-helen hmsg-typing"><span className="helen-tick" style={{ background: accent }} />Burnzee is thinking…</div> : null}
            </div>
            {canReteach ?
          <div className="helen-reteach-row">
                <button className="helen-reteach" onClick={reteach} style={{ borderColor: accent, color: accent }}>
                  <Icon name="refresh" size={18} /> Re-teach {secLabel} with new material
                </button>
              </div> :
          null}
            {msgs.length <= 1 ?
          <div className="helen-suggest">
                {suggestions.map((s, i) => <button key={i} className="helen-chip" onClick={() => send(s)}>{s}</button>)}
              </div> :
          null}
            <div className="helen-compose">
              <textarea className="helen-textarea" rows={1} value={input} placeholder="Ask Burnzee…"
            onChange={(e) => setInput(e.target.value)}
            onKeyDown={(e) => {if (e.key === "Enter" && !e.shiftKey) {e.preventDefault();send();}}} />
              <button className="helen-send" onClick={() => send()} disabled={busy || !input.trim()} aria-label="Send">
                <Icon name="send" size={20} />
              </button>
            </div>
          </div>) : (

        /* ===== SCRIPTED FALLBACK (no backend yet) ===== */
        <>
            <div className="helen-thread">
              {scriptLines.slice(0, shown).map((t, i) =>
            <div key={i} className="helen-bubble"><span className="helen-tick" style={{ background: accent }} />{t}</div>
            )}
              {shown >= scriptLines.length && canReteach ?
            <div className="helen-bubble helen-offer">
                  <span className="helen-tick" style={{ background: accent }} />
                  Want me to re-teach <b>{secLabel}</b>? I'll refresh the page with fresh material.
                </div> :
            null}
            </div>
            {shown < scriptLines.length ?
          <button className="helen-more" onClick={() => setShown((s) => s + 1)} style={{ color: accent }}>Go on…</button> :
          null}
            {canReteach ?
          <button className="helen-reteach" onClick={reteach} style={{ borderColor: accent, color: accent }}>
                <Icon name="refresh" size={18} /> Re-teach {secLabel} with new material
              </button> :
          null}
            <div className="helen-setup">
              <b>Want Burnzee to actually talk back?</b> Connect Burnzee to your AI and he'll hold real conversations, quiz you, and remember across sessions. <button className="link-helen" onClick={onOpenSettings}>Set up Burnzee →</button>
            </div>
          </>)
        }
      </aside>
    </>);

}

/* ---------- SETTINGS (connect to your Cloudflare Worker) ---------- */
function SettingsModal({ open, onClose }) {
  const api = window.LPApi;
  const [cfg, setCfg] = useStateS(() => api ? api.config() : { url: "", key: "", model: "google/gemini-flash-1.5", profile: "default" });
  const [test, setTest] = useStateS(null); // {ok, msg}
  const [testing, setTesting] = useStateS(false);
  useEffectS(() => {if (open && api) setCfg(api.config());setTest(null);}, [open]);
  if (!open) return null;

  function save() {api.saveConfig(cfg);onClose();}
  async function runTest() {
    api.saveConfig(cfg);setTesting(true);setTest(null);
    try {
      await api.ping();
      const reply = await api.chat([
      { role: "system", content: "You are Burnzee. Reply in one short friendly sentence." },
      { role: "user", content: "Say hello so I know the connection works." }]
      );
      setTest({ ok: true, msg: "Connected! Burnzee says: “" + (reply || "hello").trim() + "”" });
    } catch (e) {
      setTest({ ok: false, msg: e.message || "Could not connect." });
    } finally {setTesting(false);}
  }

  return (
    <div className="modal-scrim" onClick={onClose}>
      <div className="modal" onClick={(e) => e.stopPropagation()}>
        <div className="modal-head">
          <h2 className="modal-title">Connect Burnzee</h2>
          <button className="iconbtn" onClick={onClose}>✕</button>
        </div>
        <p className="modal-sub">Point the app at your Cloudflare Worker. These settings stay on this device only — your API key never leaves the Worker.</p>

        <div className="field">
          <label className="field-label">Worker URL</label>
          <input className="field-input" value={cfg.url} placeholder="https://language-partner-worker.you.workers.dev"
          onChange={(e) => setCfg({ ...cfg, url: e.target.value })} />
          <div className="field-hint">The address Wrangler printed when you deployed the Worker.</div>
        </div>

        <div className="field">
          <label className="field-label">Passphrase</label>
          <input className="field-input" type="password" value={cfg.key} placeholder="your APP_PASSPHRASE"
          onChange={(e) => setCfg({ ...cfg, key: e.target.value })} />
          <div className="field-hint">The same phrase you set with <code>wrangler secret put APP_PASSPHRASE</code>.</div>
        </div>

        <div className="field">
          <label className="field-label">Model</label>
          <select className="field-select" value={cfg.model} onChange={(e) => setCfg({ ...cfg, model: e.target.value })}>
            {api.MODELS.map((m) => <option key={m.id} value={m.id}>{m.label}</option>)}
          </select>
          <div className="field-hint">Cheapest first. You can change this anytime.</div>
        </div>

        <div className="field">
          <label className="field-label">Profile (for syncing progress)</label>
          <input className="field-input" value={cfg.profile} placeholder="default"
          onChange={(e) => setCfg({ ...cfg, profile: e.target.value })} />
          <div className="field-hint">Leave as “default” unless you keep separate profiles.</div>
        </div>

        <div className="modal-actions">
          <button className="btn-primary" onClick={save}>Save</button>
          <button className="btn-text" onClick={runTest} disabled={testing || !cfg.url || !cfg.key}>{testing ? "Testing…" : "Test connection"}</button>
          {test ? <div className={"test-result " + (test.ok ? "ok" : "no")}>{test.msg}</div> : null}
        </div>

        <div className="modal-foot">Everything runs on your own Cloudflare account. See DEPLOY.md for setup and PRIVACY.md for what is and isn't stored.</div>
      </div>
    </div>);

}

Object.assign(window, { Dashboard, LanguagePage, BurnzeePanel, SettingsModal, SECTION_META });