/* daily.jsx — Today's Drill: 3 questions a day, spaced review.
   Selection is seeded by the date (same 3 questions all day):
     · prefer chapters the learner has completed (hte-progress)
     · strongly prefer questions previously missed (hte-daily.history)
     · otherwise rotate through least-recently-seen
   State in localStorage 'hte-daily':
     { lastDone: 'YYYY-MM-DD', streak, history: { [qid]: { seen, missed } } } */

const { useState: dlUseState, useEffect: dlUseEffect, useMemo: dlUseMemo } = React;

const DL_TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "theme": "paper",
  "audience": "adult"
}/*EDITMODE-END*/;

const dlToday = () => new Date().toISOString().slice(0, 10);

function dlLoad() {
  try { return JSON.parse(localStorage.getItem("hte-daily") || "{}"); } catch (e) { return {}; }
}
function dlSave(d) {
  try { localStorage.setItem("hte-daily", JSON.stringify(d)); } catch (e) {}
}

// Deterministic RNG from a string seed (mulberry32 over a simple hash)
function dlSeeded(seed) {
  let h = 1779033703 ^ seed.length;
  for (let i = 0; i < seed.length; i++) {
    h = Math.imul(h ^ seed.charCodeAt(i), 3432918353);
    h = (h << 13) | (h >>> 19);
  }
  return function () {
    h = Math.imul(h ^ (h >>> 16), 2246822507);
    h = Math.imul(h ^ (h >>> 13), 3266489909);
    h ^= h >>> 16;
    return (h >>> 0) / 4294967296;
  };
}

/* Pick today's 3 questions. */
function dlPick(date) {
  const rnd = dlSeeded("hte-" + date);
  let progress = {};
  try { progress = JSON.parse(localStorage.getItem("hte-progress") || "{}"); } catch (e) {}
  const hist = (dlLoad().history) || {};
  const doneCh = new Set(Object.keys(progress).filter(k => progress[k] === "done"));
  const anyDone = doneCh.size > 0;

  const scored = DAILY_BANK.map(q => {
    const h = hist[q.id] || { seen: 0, missed: 0 };
    let w = 1;
    if (anyDone && doneCh.has(q.ch)) w += 2;          // review what you've learned
    w += Math.min(3, h.missed * 2);                    // re-ask what you've missed
    w += h.seen === 0 ? 1 : 0;                         // mild novelty bonus
    w /= (1 + h.seen * 0.35);                          // fade things seen often
    return { q, w, r: rnd() };
  });

  // weighted sample without replacement, deterministic via r
  scored.sort((a, b) => (Math.pow(a.r, 1 / a.w)) < (Math.pow(b.r, 1 / b.w)) ? 1 : -1);
  // diversify: avoid 2 questions from the same chapter when possible
  const picked = [];
  for (const s of scored) {
    if (picked.length >= 3) break;
    if (picked.some(p => p.ch === s.q.ch) && scored.length - picked.length > 3) continue;
    picked.push(s.q);
  }
  while (picked.length < 3) {
    const s = scored.find(x => !picked.includes(x.q));
    if (!s) break;
    picked.push(s.q);
  }
  return picked;
}

function DlApp() {
  const [t, setTweak] = useTweaks(DL_TWEAK_DEFAULTS);
  useCrossChapterPersistence(t, setTweak);
  dlUseEffect(() => { document.body.setAttribute("data-theme", t.theme); }, [t.theme]);
  const kids = t.audience === "kids";

  const today = dlToday();
  const questions = dlUseMemo(() => dlPick(today), [today]);
  const store = dlLoad();
  const alreadyDone = store.lastDone === today;

  // per-question presentation shuffle (stable per day)
  const shuffled = dlUseMemo(() => {
    const rnd = dlSeeded("hte-shuffle-" + today);
    return questions.map(q => {
      const order = q.options.map((_, i) => i).sort(() => rnd() - 0.5);
      return { ...q, order, correctAt: order.indexOf(q.correct) };
    });
  }, [questions, today]);

  const [answers, setAnswers] = dlUseState({});
  const answeredAll = Object.keys(answers).length === shuffled.length;
  const score = shuffled.reduce((acc, q, i) => acc + (answers[i] === q.correctAt ? 1 : 0), 0);

  // commit on completion: streak + history
  dlUseEffect(() => {
    if (!answeredAll || alreadyDone) return;
    const d = dlLoad();
    const hist = d.history || {};
    shuffled.forEach((q, i) => {
      const h = hist[q.id] || { seen: 0, missed: 0 };
      h.seen += 1;
      if (answers[i] !== q.correctAt) h.missed += 1;
      else h.missed = Math.max(0, h.missed - 1);
      hist[q.id] = h;
    });
    const yesterday = new Date(Date.now() - 86400000).toISOString().slice(0, 10);
    const streak = d.lastDone === yesterday ? (d.streak || 0) + 1 : 1;
    dlSave({ ...d, lastDone: today, streak, history: hist });
  }, [answeredAll]);

  const streak = (dlLoad().streak) || 0;

  return (
    <>
      <ProgressBar />
      <TopBar chapterLabel="Today's Drill" audience={t.audience}
              setAudience={(a) => setTweak("audience", a)} />

      <main>
        <section className="section" id="daily" data-screen-label="Daily drill" style={{ paddingTop: "13vh", minHeight: "100vh" }}>
          <div className="section-inner" style={{ maxWidth: 760 }}>
            <div className="eyebrow" style={{ marginBottom: 10 }}>
              today's drill · {today}{streak > 1 ? ` · ${streak}-day streak` : ""}
            </div>
            <h1 className="serif" style={{ fontSize: "clamp(32px, 5vw, 50px)", margin: "0 0 10px" }}>
              {alreadyDone && !answeredAll
                ? <>Done for today. <em>Come back tomorrow.</em></>
                : <>Three questions.<br/><em>Three minutes.</em></>}
            </h1>
            <p className="lede">
              {kids
                ? <>A tiny daily brain-wake-up! It remembers what tripped you up and sneaks those back in.</>
                : <>Spaced review across everything you've covered — weighted toward chapters you've finished and questions you've missed before. Same three for everyone today; fresh three tomorrow.</>}
            </p>

            {alreadyDone && !answeredAll && (
              <div className="card" style={{ marginTop: 24, padding: "26px 30px" }}>
                <p style={{ margin: 0, fontSize: 16 }}>
                  {kids
                    ? <>You already did today's three — nice! Your streak is safe. Want more right now? The chapter quizzes always have fresh draws.</>
                    : <>Today's set is logged{streak > 1 ? <> — streak at <b>{streak} days</b></> : ""}. The bank refreshes at midnight. For more reps now, any chapter quiz can deal "5 fresh questions."</>}
                </p>
                <div style={{ display: "flex", gap: 12, marginTop: 18, flexWrap: "wrap" }}>
                  <PrevChapterButton href="map.html" label="Course map" />
                  <NextChapterButton href="sandbox.html" label="The Workbench" />
                </div>
              </div>
            )}

            {(!alreadyDone || answeredAll) && (
              <div style={{ marginTop: 26 }}>
                {shuffled.map((q, qi) => {
                  const picked = answers[qi];
                  const isDone = picked !== undefined;
                  const chMeta = ALL_CHAPTERS.find(c => c.n === q.ch);
                  return (
                    <div key={q.id} className="quiz-q" style={{ marginTop: qi ? 18 : 0, padding: "20px 24px" }}>
                      <div className="eyebrow" style={{ marginBottom: 8, fontSize: 10 }}>
                        {qi + 1} / 3 · from ch. {q.ch}{chMeta ? ` — ${chMeta.t}` : ""}
                      </div>
                      <p className="quiz-q-text" style={{ fontSize: 19 }}><Eq>{kids ? q.q.kids : q.q.adult}</Eq></p>
                      <div className="quiz-opts">
                        {q.order.map((origIdx, oi) => {
                          let cls = "";
                          if (isDone) {
                            if (oi === q.correctAt) cls = "correct";
                            else if (oi === picked) cls = "wrong";
                          }
                          return (
                            <button key={oi} className={cls} disabled={isDone}
                                    onClick={() => setAnswers(prev => prev[qi] !== undefined ? prev : { ...prev, [qi]: oi })}>
                              <span className="letter">{String.fromCharCode(65 + oi)}</span>
                              <span><Eq>{q.options[origIdx]}</Eq></span>
                              {isDone && oi === q.correctAt && <span className="tick">✓</span>}
                              {isDone && oi === picked && oi !== q.correctAt && <span className="cross">✕</span>}
                            </button>
                          );
                        })}
                      </div>
                      {isDone && (
                        <div className={`quiz-explain ${picked === q.correctAt ? "correct" : "wrong"}`}>
                          <Eq>{kids ? q.explain.kids : q.explain.adult}</Eq>
                        </div>
                      )}
                    </div>
                  );
                })}

                {answeredAll && (
                  <div className="card" style={{ marginTop: 22, padding: "22px 26px" }}>
                    <p style={{ margin: 0, fontFamily: "IBM Plex Mono, monospace", fontSize: 15,
                                color: score === 3 ? "var(--water-deep)" : "var(--ink-soft)" }}>
                      {score}/3 {score === 3 ? (kids ? "— perfect! See you tomorrow." : "— clean sweep. Logged; see you tomorrow.")
                        : (kids ? "— the tricky ones will sneak back soon!" : "— misses noted; they'll come back around.")}
                      {" "}{streak >= 1 && `Streak: ${dlLoad().streak} day${dlLoad().streak === 1 ? "" : "s"}.`}
                    </p>
                    <div style={{ display: "flex", gap: 12, marginTop: 16, flexWrap: "wrap" }}>
                      <PrevChapterButton href="map.html" label="Course map" />
                      <NextChapterButton href="sandbox.html" label="The Workbench" />
                    </div>
                  </div>
                )}
              </div>
            )}
          </div>
        </section>
      </main>

      <TweaksPanel title="Tweaks">
        <CommonTweaks t={t} setTweak={setTweak} />
      </TweaksPanel>
      <GlossaryFab />
    </>
  );
}

ReactDOM.createRoot(document.getElementById("root")).render(<DlApp />);
