// =====================================================================
// irikos — Student side of Classrooms.
// Class home (my classes · pending-invite banner · join by code) and
// Homework (assigned list with statuses; completed shows score / missed /
// teacher note). Doing homework reuses the existing practice UI via
// onStartHomework. Globals: React, store helpers, shared components.
// =====================================================================

const { useState: stUseState, useEffect: stUseEffect } = React;

function StudentClass({ store, actions, account, pushToast, dataState, onStartHomework, initialTab }) {
  const [tab, setTab] = stUseState(initialTab || "home");

  // make the student's homework read realistically the first time they're a member
  stUseEffect(() => {
    if ((store.studentMemberships[account.handle] || []).length > 0) {
      actions.seedStudentHomework(account.handle);
    }
  }, []); // eslint-disable-line

  const invites = studentPendingInvites(store, account.handle);
  const memberOf = (store.studentMemberships[account.handle] || []).map(id => store.classrooms[id]).filter(Boolean);
  const hw = studentAssignments(store, account.handle);

  const tabs = [
    { id: "home", label: "My class", count: memberOf.length || null },
    { id: "homework", label: "Homework", count: hw.length || null },
  ];

  return (
    <div className="class-shell">
      <header className="class-head">
        <div className="class-head-l">
          <h1 className="class-title">Class</h1>
          <span className="role-chip is-student">Student</span>
        </div>
      </header>

      <Tabs tabs={tabs} active={tab} onChange={setTab} />

      {dataState === "loading" && <SkeletonRows n={3} />}
      {dataState === "error" && <ErrorState onRetry={() => pushToast("Reconnected")}>Couldn't reach your class just now.</ErrorState>}

      {dataState === "ready" && tab === "home" && (
        <StudentHome store={store} actions={actions} account={account} pushToast={pushToast}
          invites={invites} memberOf={memberOf} onSeeHomework={() => setTab("homework")} />
      )}
      {dataState === "ready" && tab === "homework" && (
        <StudentHomework store={store} account={account} hw={hw} onStartHomework={onStartHomework} />
      )}
    </div>
  );
}

// ---------------------------------------------------------------------
// Class home
// ---------------------------------------------------------------------
function StudentHome({ store, actions, account, pushToast, invites, memberOf, onSeeHomework }) {
  const [roster, setRoster] = React.useState(null);
  return (
    <>
      {invites.map(inv => (
        <PendingInvite key={inv.classId} inv={inv} actions={actions} account={account} pushToast={pushToast} onSeeHomework={onSeeHomework} />
      ))}

      {memberOf.length === 0 && invites.length === 0 ? (
        <EmptyState icon="○" title="You're not in a class yet"
          cta={<JoinByCode actions={actions} account={account} pushToast={pushToast} />}>
          When a teacher invites you by @{account.handle}, it shows up here. Or enter a join code they shared with you.
        </EmptyState>
      ) : (
        <>
          {memberOf.length > 0 && (
            <>
              <div className="section-label">My classes</div>
              <div className="cls-grid" style={{ marginBottom: 22 }}>
                {memberOf.map(c => {
                  const teacher = c.ownerHandle ? "@" + c.ownerHandle : classTeacherName;
                  const studentCount = c.studentCount != null ? c.studentCount : c.studentHandles.length;
                  return (
                    <div className="cls-card" key={c.id} style={{ cursor: "pointer" }} role="button" tabIndex={0}
                      onClick={() => setRoster(c)}
                      onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); setRoster(c); } }}>
                      <div className="cls-card-top">
                        <div>
                          <div className="cls-card-name">{c.name}</div>
                          <div className="cls-card-meta">{teacher} · {studentCount} {studentCount === 1 ? "student" : "students"}</div>
                        </div>
                        <span className="cls-card-chev" aria-hidden="true">→</span>
                      </div>
                      <div className="cls-card-foot">
                        <span className="badge is-ok"><span className="dot" />joined</span>
                        <button className="text-link" onClick={(e) => { e.stopPropagation(); onSeeHomework(); }}>Homework →</button>
                      </div>
                    </div>
                  );
                })}
              </div>
            </>
          )}

          <div className="panel panel-pad">
            <div className="section-label">Join another class</div>
            <JoinByCode actions={actions} account={account} pushToast={pushToast} />
          </div>
        </>
      )}
      {roster && (
        <StudentRosterModal c={roster} store={store} account={account}
          onClose={() => setRoster(null)}
          onSeeHomework={() => { setRoster(null); onSeeHomework(); }} />
      )}
    </>
  );
}

// Names-only roster a student sees when they tap their class (no stats).
function StudentRosterModal({ c, store, account, onClose, onSeeHomework }) {
  const handles = c.studentHandles || [];
  // Pull fresh scores on open so the board reflects points added moments ago.
  const [scores, setScores] = React.useState(c.studentScores || {});
  React.useEffect(() => {
    let alive = true;
    let token = null; try { token = localStorage.getItem(window.TOKEN_KEY || "vp.token.v1"); } catch (e) {}
    if (!token || !c.id) return; // demo mode (no token) keeps the seeded scores
    fetch(`/api/classrooms/${c.id}/members`, { headers: { Authorization: `Bearer ${token}` } })
      .then(r => r.json())
      .then(d => {
        if (!alive || !d || !d.members) return;
        const next = {};
        for (const m of d.members) {
          const h = (m.username || "").replace(/^@/, "");
          next[h] = { score: m.score || 0, correct: m.correct || 0, answered: m.answered || 0, best: m.best || 0, streak: m.streak || 0 };
        }
        setScores(next);
      })
      .catch(() => {});
    return () => { alive = false; };
  }, [c.id]);
  const teacher = c.ownerHandle ? "@" + c.ownerHandle : null;
  // Rank by total points (score); tiebreak best game → correct → name.
  const ranked = handles.slice().sort((a, b) => {
    const sa = scores[a] || {}, sb = scores[b] || {};
    return (sb.score || 0) - (sa.score || 0)
      || (sb.best || 0) - (sa.best || 0)
      || (sb.correct || 0) - (sa.correct || 0)
      || a.localeCompare(b);
  });
  return (
    <Modal title={c.name} sub={`Leaderboard · ${handles.length} ${handles.length === 1 ? "student" : "students"}${teacher ? " · " + teacher : ""}`} onClose={onClose}
      foot={<button className="cta-primary" onClick={onSeeHomework}><span>Homework</span><span className="cta-arrow">→</span></button>}>
      {handles.length === 0 ? (
        <p className="muted" style={{ margin: 0 }}>No other students have joined yet.</p>
      ) : (
        <div className="lb-list">
          {ranked.map((h, i) => {
            const p = store.directory[h] || { name: "@" + h, avatarHue: 200, handle: h };
            const sc = scores[h] || {};
            const you = h === account.handle;
            const Flame = (typeof window !== "undefined" && window.Flame) || null;
            const TIERS = (typeof window !== "undefined" && window.STREAK_TIERS) || [];
            const tIdx = (typeof window !== "undefined" && window.tierIndexFor) ? Math.max(0, window.tierIndexFor(sc.streak || 0)) : 0;
            const glow = (TIERS[tIdx] || {}).glow || "var(--ink-3)";
            return (
              <div key={h} className={`lb-row${you ? " is-you" : ""}`}>
                <span className={`lb-rank${i < 3 ? " is-top" : ""}`}>{i + 1}</span>
                <Avatar name={p.name} hue={p.avatarHue} size="sm" />
                <span className="lb-name">{p.name}{you ? " (you)" : ""}</span>
                {sc.streak > 0 && Flame && (
                  <span className="lb-streak" title={`${sc.streak}-day streak`}>
                    <span className="lb-streak-pet"><Flame days={sc.streak} px={24} variant="chip" /></span>
                    <span className="lb-streak-n" style={{ color: glow }}>{sc.streak}</span>
                  </span>
                )}
                <span className="lb-score">{(sc.score || 0).toLocaleString()}<span className="lb-score-u">points</span></span>
              </div>
            );
          })}
        </div>
      )}
    </Modal>
  );
}

function PendingInvite({ inv, actions, account, pushToast, onSeeHomework }) {
  const c = inv.classroom;
  return (
    <div className={`invite-banner ${inv.demo ? "is-fresh" : ""}`}>
      <div>
        <div className="invite-kicker">Class invitation</div>
        <div className="invite-h"><b>{c.ownerHandle ? "@" + c.ownerHandle : classTeacherName}</b> invited you to join <b>{c.name}</b></div>
        <div className="invite-shares">
          <div className="shares-label">What you'll share with your teacher</div>
          <div className="shares-list">
            <div className="share-item"><span className="tick">✓</span> Your practice stats — accuracy by family, streak, and activity</div>
            <div className="share-item"><span className="tick">✓</span> Homework they assign you, auto-scored on submit</div>
            <div className="share-item no"><span className="tick">○</span> Nothing else — not your password, and no practice outside this app</div>
          </div>
        </div>
      </div>
      <div className="invite-actions">
        <button className="cta-primary" onClick={() => { actions.acceptInvite(c.id, account.handle); pushToast(`Joined ${c.name}`); onSeeHomework(); }}>
          <span>Accept</span><span className="cta-arrow">→</span>
        </button>
        <button className="cta-secondary" onClick={() => { if (!inv.demo) actions.declineInvite(c.id, account.handle); pushToast("Invitation declined"); }}>Decline</button>
      </div>
    </div>
  );
}

function JoinByCode({ actions, account, pushToast }) {
  const [code, setCode] = stUseState("");
  const [err, setErr] = stUseState("");
  const join = async () => {
    if (code.trim().length < 4) { setErr("Enter the 6-character code."); return; }
    const found = await actions.joinByCode(code.trim(), account.handle);
    if (found) { pushToast("Joined class"); setCode(""); setErr(""); }
    else setErr("No class found for that code. Double-check with your teacher.");
  };
  return (
    <div>
      <div className="join-row">
        <input className="join-input" value={code} maxLength={8} onChange={e => { setCode(e.target.value.toUpperCase()); setErr(""); }}
          onKeyDown={e => e.key === "Enter" && join()} placeholder="CODE" aria-label="Join code" />
        <button className="cta-primary" onClick={join}><span>Join</span><span className="cta-arrow">→</span></button>
      </div>
      {err && <div className="auth-error" style={{ marginTop: 8 }}>{err}</div>}
    </div>
  );
}

// ---------------------------------------------------------------------
// Homework list + result detail
// ---------------------------------------------------------------------
function StudentHomework({ store, account, hw, onStartHomework }) {
  const [open, setOpen] = stUseState(null);

  if (hw.length === 0) {
    return <EmptyState icon="○" title="No homework right now">When your teacher assigns something, it lands here with its due date. You'll get a heads-up the moment it does.</EmptyState>;
  }

  // sort: actionable first (overdue, not-started, in-progress), completed last
  const order = { overdue: 0, "in-progress": 1, "not-started": 2, completed: 3 };
  const sorted = hw.slice().sort((a, b) => (order[a.sub.status] - order[b.sub.status]));

  return (
    <div className="panel">
      {sorted.map(a => {
        const sub = a.sub;
        const isOpen = open === a.id;
        const actionable = sub.status !== "completed";
        return (
          <div key={a.id}>
            <div className="hw-row" style={{ cursor: actionable ? "default" : "pointer" }}
              onClick={() => { if (!actionable) setOpen(isOpen ? null : a.id); }}>
              <div className="hw-main">
                <div className="hw-eyebrow">
                  <span className="task-tag" data-task={a.kind.type === "set" ? a.kind.family : (a.kind.type === "test" ? CATEGORY_META[a.kind.categoryId]?.family : "word-formation")}>{assignmentLabel(a.kind)}</span>
                  <StatusPill status={sub.status} />
                </div>
                <div className="hw-title">{a.title}</div>
                {a.note && <div className="hw-note">{a.note}</div>}
                <div className="hw-meta">
                  <span className={`hw-due ${sub.status === "overdue" ? "is-overdue" : ""}`}>Due {fmtDue(a.dueDate)}</span>
                  {sub.status === "in-progress" && <span>{sub.answered}/{sub.total} answered</span>}
                </div>
              </div>
              <div className="hw-right">
                {sub.status === "completed" ? (
                  <>
                    <div className="hw-count">{sub.correct}/{sub.total}</div>
                    <span className="acc-pill" data-lvl={accLvl(sub.accuracy)}>{Math.round(sub.accuracy * 100)}%</span>
                    <span className="text-link">{isOpen ? "Hide" : "View result"}</span>
                  </>
                ) : (
                  <button className="cta-primary" onClick={(e) => { e.stopPropagation(); onStartHomework(a); }}>
                    <span>{sub.status === "in-progress" ? "Resume" : "Start"}</span><span className="cta-arrow">→</span>
                  </button>
                )}
              </div>
            </div>
            {isOpen && sub.status === "completed" && (
              <HomeworkResult a={a} sub={sub} teacher={store.classrooms[a.classroomId]?.ownerHandle} />
            )}
          </div>
        );
      })}
    </div>
  );
}

function HomeworkResult({ a, sub, teacher }) {
  const missedItems = (sub.missed || []).map(id => VOCAB.find(v => v.id === id)).filter(Boolean);
  return (
    <div className="panel-pad" style={{ borderTop: "1px solid var(--rule)", background: "var(--bg-2)" }}>
      <div className="results-grid" style={{ borderTop: 0, borderBottom: missedItems.length ? "1px solid var(--rule)" : 0, paddingTop: 0 }}>
        <div className="result-stat"><div className="result-stat-label">Score</div><div className="result-stat-value">{sub.score}</div></div>
        <div className="result-stat"><div className="result-stat-label">Correct</div><div className="result-stat-value">{sub.correct}/{sub.total}</div></div>
        <div className="result-stat"><div className="result-stat-label">Accuracy</div><div className="result-stat-value">{Math.round(sub.accuracy * 100)}%</div></div>
      </div>

      {sub.feedbackNote && (
        <div className="invite-banner" style={{ margin: "16px 0 0", display: "block", padding: "16px 18px" }}>
          <div className="shares-label" style={{ marginBottom: 6 }}>Note from {teacher ? "@" + teacher : classTeacherName}</div>
          <div style={{ fontSize: 14, color: "var(--ink-2)", fontStyle: "italic" }}>“{sub.feedbackNote}”</div>
        </div>
      )}

      {missedItems.length > 0 && (
        <>
          <div className="section-label" style={{ margin: "18px 0 12px" }}>Questions you missed · {missedItems.length}</div>
          <ul className="mistake-list">
            {missedItems.map(it => (
              <li className="mistake-row" key={it.id}>
                <div className="mistake-main">
                  <div className="mistake-eyebrow">
                    <span className="task-tag" data-task={it.type}>{FAMILY_META[it.type]?.label}</span>
                    {it.base && <span className="mistake-base">{it.base}</span>}
                  </div>
                  <div className="mistake-sentence">{(it.sentence || it.text || "").replace(/⟦\d+⟧/g, " ______ ").replace(/_{2,}/g, "______")}</div>
                  <div className="mistake-answer">Answer <b>{it.gaps ? it.gaps.map(g => g.answer).join(", ") : it.answer}</b></div>
                </div>
              </li>
            ))}
          </ul>
        </>
      )}
    </div>
  );
}

Object.assign(window, { StudentClass });
