/* ============================================================
   Guided Workshop — Results tab (revamped)

   Composition:
     1. Header        — title + "Result options" dropdown
     2. Stat grid     — 4 KPI cards (Attendance / Overall score
                        / Score type / Actions)
     3. Score breakdown — collapsible table by chapter showing
                          per-item score-type / question-type / score
     4. Question overview — one detail card per item with the
                            actual content + distribution + AI summary

   Exports: window.ResultsTabRevamped
   Reads:   window.GW_CHAPTERS, GW_ACTIONS
            window.gwViews.ContentView etc (for re-using item bodies)
   ============================================================ */

const { useState: rUseState, useMemo: rUseMemo, useEffect: rUseEffect, useRef: rUseRef } = React;

/* ---------- Deterministic mock helpers ----------
   Scores and distributions need to be stable across renders, so we
   derive everything from the item id via a tiny xfnv1a-style hash. */
function rHash(str) {
  let h = 2166136261;
  for (let i = 0; i < str.length; i++) {
    h ^= str.charCodeAt(i);
    h = Math.imul(h, 16777619);
  }
  return h >>> 0;
}
function rRand(seed) {
  /* mulberry32 */
  let t = seed + 0x6D2B79F5;
  t = Math.imul(t ^ (t >>> 15), t | 1);
  t ^= t + Math.imul(t ^ (t >>> 7), t | 61);
  return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
}

/* Score-type assignment: pick "Understanding", "Compliance",
   or "Performance" per item based on its semantic role.
   Heuristics:
     - content    → Understanding
     - media      → Understanding
     - evidence   → Compliance
     - question/textarea/text → Compliance
     - question/rating/boolean → Performance
     - question/radio (poll)   → mix — let id hash decide
*/
function scoreTypeFor(item) {
  if (!item) return "Understanding";
  if (item.type === "content" || item.type === "media") return "Understanding";
  if (item.type === "evidence") return "Compliance";
  if (item.type === "question") {
    const q = item.questionType;
    if (q === "rating" || q === "boolean") return "Performance";
    if (q === "textarea" || q === "text")  return "Compliance";
    /* radio — use hash */
    return (rHash(item.id) % 3 === 0) ? "Performance"
         : (rHash(item.id) % 3 === 1) ? "Understanding"
         :                              "Compliance";
  }
  return "Understanding";
}

/* Per-item score on the 0–10 scale (matches the screenshot). */
function scoreFor(item) {
  const r = rRand(rHash(item.id || "x"));
  /* skew toward 4–8 to feel realistic */
  return Math.round((3 + r * 6) * 10) / 10;
}

/* Action count per item — small integers. */
function actionsFor(item) {
  const r = rRand(rHash("a_" + (item.id || "x")));
  return Math.floor(r * 6); /* 0..5 */
}

/* ---------- Distribution helpers ----------
   Build a question-type-shaped distribution for ANY question item, poll
   or individual. Mirrors computeDistribution from gwViews but doesn't
   require session data — we manufacture a plausible response count
   from the item id so individual questions also show results. */
const RT_TEXT_RESPONSES = [
  "No blame, early speak up culture",
  "Aligned strategy to shift outcomes in a positive way for next 12 months",
  "More time spent targeting male middle aged employees",
  "Improved selection process",
  "1) Improve recruiting to ensure values fit for key roles, particularly leaders at all levels. Psychometric values fit testing? 2) share incidents, investigation findings and outcomes with leaders",
  "Improved selection process",
  "Aligned strategy to shift outcomes in a positive way for next 12 months",
  "Improved selection process",
];
const RT_TEXTAREA_RESPONSES = [
  "\"I think our teams know, but they don't necessarily like it.\" \"Some of the teams actively pushing against it.\"",
  "\"From front-line, not everyone necessarily believes it is their accountability. They may call it out, but not necessarily their accountability.\" \"Helping leaders with further engaging in discussion when they get push-back and challenge on \"you are pushing me\"\"",
  "\"Teams may not have a clear understanding to identify the lower level hazards.\" On a journey here.",
  "50 — \"Still think half our workforce dont get this.\" >3000 odd people. Example shared of incident on-site with two females in the room and a comment made. Leader addressed.",
];

function syntheticDist(item) {
  if (!item || item.type !== "question") return null;
  const seed = rHash(item.id);
  const total = 30 + (seed % 80); /* 30..109 "responses" */
  const t = item.questionType;
  if (t === "radio") {
    const opts = item.options || [];
    const N = opts.length || 1;
    /* Distribute total across options with a skew. */
    const weights = Array.from({ length: N }, (_, i) => {
      const r = rRand(seed + i * 31);
      return 0.3 + r * 1.2;
    });
    const sumW = weights.reduce((a, b) => a + b, 0);
    const counts = weights.map(w => Math.max(1, Math.round((w / sumW) * total)));
    return { counts, labels: opts, total };
  }
  if (t === "rating") {
    const max = item.scale?.max || 5;
    const min = item.scale?.min || 1;
    const N = max - min + 1;
    const raw = Array.from({ length: N }, (_, i) => {
      const r = rRand(seed + i * 11);
      const weight = 0.3 + Math.abs(Math.sin((i / Math.max(1, N - 1)) * Math.PI)) * 1.2;
      return Math.max(1, Math.round(r * 100 * weight));
    });
    const sumW = raw.reduce((a, b) => a + b, 0);
    const counts = raw.map(c => Math.max(0, Math.round((c / sumW) * total)));
    return { counts, max, min, total };
  }
  if (t === "boolean") {
    const yesPct = 40 + (seed % 35);
    const yes = Math.round((yesPct / 100) * total);
    return { yes, no: total - yes, total };
  }
  if (t === "text") {
    const n = Math.min(RT_TEXT_RESPONSES.length, Math.max(3, total % 9));
    return { responses: RT_TEXT_RESPONSES.slice(0, n), total };
  }
  if (t === "textarea") {
    const n = Math.min(RT_TEXTAREA_RESPONSES.length, Math.max(3, total % 6));
    return { responses: RT_TEXTAREA_RESPONSES.slice(0, n), total };
  }
  return null;
}

/* Health % from a per-questionType dist:
   - radio:   percent of responses in the "top half" of options
   - rating:  percent at or above the midpoint
   - boolean: yes percent
   - text/area: percent of responders (== 100 by definition) */
function healthFromDist(item, dist) {
  if (!dist) return 0;
  const t = item.questionType;
  const total = dist.total || dist.counts?.reduce((a, b) => a + b, 0) || 0;
  if (total === 0) return 0;
  if (t === "radio") {
    const N = dist.counts.length;
    const half = Math.ceil(N / 2);
    const top = dist.counts.slice(0, half).reduce((a, b) => a + b, 0);
    return Math.round((top / total) * 100);
  }
  if (t === "rating") {
    const counts = dist.counts;
    const mid = Math.ceil(counts.length / 2);
    const top = counts.slice(mid).reduce((a, b) => a + b, 0);
    return Math.round((top / total) * 100);
  }
  if (t === "boolean") return Math.round((dist.yes / total) * 100);
  return 100;
}

/* Average for rating/radio (for the stat card) */
function averageFromDist(item, dist) {
  if (!dist) return 0;
  const t = item.questionType;
  if (t === "rating") {
    const total = dist.counts.reduce((a, b) => a + b, 0);
    if (!total) return 0;
    const sum = dist.counts.reduce((acc, c, i) => acc + c * (dist.min + i), 0);
    return sum / total;
  }
  if (t === "radio") {
    const total = dist.counts.reduce((a, b) => a + b, 0);
    if (!total) return 0;
    const sum = dist.counts.reduce((acc, c, i) => acc + c * (i + 1), 0);
    return sum / total;
  }
  return 0;
}

/* Per-question type bucket label (the "Question type" column in the
   screenshot — Formal / Poll / Initial / etc). */
function questionTypeFor(item) {
  if (!item) return null;
  if (item.type === "question" && item.mode === "poll") return "Poll";
  if (item.type === "question") return "Formal";
  if (item.type === "evidence") return "Initial";
  if (item.type === "media") return "Formal";
  if (item.type === "content") return "Formal";
  return null;
}

/* Letter grade band from 0..10 score */
function gradeFor(score) {
  if (score >= 8.5) return "A+";
  if (score >= 7.5) return "A";
  if (score >= 6.5) return "B";
  if (score >= 5.5) return "C";
  if (score >= 4.0) return "D";
  return "F";
}
function gradeTone(grade) {
  if (grade === "A+" || grade === "A") return "green";
  if (grade === "B" || grade === "C")  return "amber";
  return "red";
}

/* Health score (%) derived from a per-question-type distribution. */
function healthScoreFromItem(item) {
  if (!item || item.type !== "question") return 0;
  const d = syntheticDist(item);
  return healthFromDist(item, d);
}

/* ---------- Icons ---------- */
const rIcons = {
  attendance: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><circle cx="9" cy="8" r="3.5"/><circle cx="17" cy="10" r="2.5"/><path d="M3 19a6 6 0 0 1 12 0M14 19c.5-2 2-3 4-3s3.5 1 4 3"/></svg>,
  score:      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><polyline points="3 17 9 11 13 15 21 7"/><polyline points="14 7 21 7 21 14"/></svg>,
  scoreType:  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M4 4h7v7H4zM13 4h7v7h-7zM4 13h7v7H4zM13 13h7v7h-7z"/></svg>,
  actions:    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>,
  understand: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><circle cx="12" cy="12" r="9"/><path d="M9.5 9a2.5 2.5 0 0 1 5 0c0 1.5-2.5 2-2.5 3.5"/><circle cx="12" cy="17" r=".7" fill="currentColor"/></svg>,
  compliance: <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M12 2L4 6v6c0 5 3.5 9 8 10 4.5-1 8-5 8-10V6z"/><polyline points="9 12 11 14 15 10"/></svg>,
  performance:<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><polyline points="22 12 18 12 15 21 9 3 6 12 2 12"/></svg>,
  sparkle:    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5z"/><path d="M19 16l.6 1.4L21 18l-1.4.6L19 20l-.6-1.4L17 18l1.4-.6z"/></svg>,
  caret:      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>,
  download:   <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>,
  expand:     <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="6 9 12 15 18 9"/></svg>,
};

/* =====================================================================
   Stat grid — 4 KPI cards across the top
   ===================================================================== */
function ResultsStatGrid({ stats }) {
  return (
    <section className="rt-stat-grid">
      <article className="rt-stat-card rt-stat-attendance">
        <header className="rt-stat-head">
          <span className="rt-stat-icon">{rIcons.attendance}</span>
          <h3>Attendance</h3>
        </header>
        <dl className="rt-stat-rows">
          <div className="rt-stat-row"><dt>Total participants</dt><dd>{stats.participants}</dd></div>
          <div className="rt-stat-row"><dt>Total responses</dt><dd>{stats.responses}</dd></div>
        </dl>
      </article>

      <article className="rt-stat-card rt-stat-overall">
        <header className="rt-stat-head">
          <span className="rt-stat-icon">{rIcons.score}</span>
          <h3>Overall Score</h3>
        </header>
        <dl className="rt-stat-rows">
          <div className="rt-stat-row"><dt>Avg. score</dt><dd>{stats.avgScore.toFixed(1)}</dd></div>
          <div className="rt-stat-row"><dt>Health score</dt><dd>{stats.healthScore}%</dd></div>
        </dl>
      </article>

      <article className="rt-stat-card rt-stat-types">
        <header className="rt-stat-head">
          <span className="rt-stat-icon">{rIcons.scoreType}</span>
          <h3>Score type</h3>
        </header>
        <dl className="rt-stat-rows">
          <div className="rt-stat-row"><dt><ScoreTypeChip kind="Understanding" small />Understanding</dt><dd><GradePill grade={stats.grades.Understanding} /></dd></div>
          <div className="rt-stat-row"><dt><ScoreTypeChip kind="Compliance"     small />Compliance</dt>   <dd><GradePill grade={stats.grades.Compliance}    /></dd></div>
          <div className="rt-stat-row"><dt><ScoreTypeChip kind="Performance"    small />Performance</dt>  <dd><GradePill grade={stats.grades.Performance}   /></dd></div>
        </dl>
      </article>

      <article className="rt-stat-card rt-stat-actions">
        <header className="rt-stat-head">
          <span className="rt-stat-icon">{rIcons.actions}</span>
          <h3>Actions</h3>
        </header>
        <dl className="rt-stat-rows">
          <div className="rt-stat-row"><dt><span className="rt-dot rt-dot-amber" />Opportunity</dt><dd>{stats.actions.opportunity}</dd></div>
          <div className="rt-stat-row"><dt><span className="rt-dot rt-dot-blue"  />Action</dt>     <dd>{stats.actions.action}</dd></div>
          <div className="rt-stat-row"><dt><span className="rt-dot rt-dot-green" />Feedback</dt>   <dd>{stats.actions.feedback}</dd></div>
        </dl>
      </article>
    </section>
  );
}

function ScoreTypeChip({ kind, small }) {
  const icon = kind === "Understanding" ? rIcons.understand
             : kind === "Compliance"    ? rIcons.compliance
             :                            rIcons.performance;
  return (
    <span className={`rt-st-chip rt-st-${kind.toLowerCase()} ${small ? "is-small" : ""}`} title={kind}>
      {icon}
    </span>
  );
}

function GradePill({ grade }) {
  return <span className={`rt-grade rt-grade-${gradeTone(grade)}`}>{grade}</span>;
}

/* =====================================================================
   Score breakdown — collapsible table, one row per chapter, each
   chapter expanding to per-item rows.
   ===================================================================== */
function ScoreBreakdownTable({ chapters }) {
  const [open, setOpen] = rUseState(() => new Set([chapters[1]?.id])); /* default-expand chapter 2 */
  const toggle = (id) => setOpen(prev => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n; });

  return (
    <section className="rt-section">
      <header className="rt-section-head">
        <h2>Score breakdown</h2>
        <p>View scores of different categories of questions and actions.</p>
      </header>
      <div className="rt-table-wrap">
        <table className="rt-table">
          <colgroup>
            <col className="rt-col-name" />
            <col className="rt-col-type" />
            <col className="rt-col-qtype" />
            <col className="rt-col-score" />
            <col className="rt-col-act" />
          </colgroup>
          <thead>
            <tr>
              <th>Module name</th>
              <th>Score type</th>
              <th>Question type</th>
              <th>Score</th>
              <th>Actions</th>
            </tr>
          </thead>
          <tbody>
            {chapters.map((c) => {
              const isOpen = open.has(c.id);
              const chapterScore = c.items.length
                ? Math.round((c.items.reduce((s, it) => s + scoreFor(it), 0) / c.items.length) * 10) / 10
                : 0;
              const chapterActions = c.items.reduce((s, it) => s + actionsFor(it), 0);
              return (
                <React.Fragment key={c.id}>
                  <tr className={`rt-tr-chapter ${isOpen ? "is-open" : ""}`} onClick={() => toggle(c.id)}>
                    <td>
                      <button className="rt-chapter-toggle" aria-expanded={isOpen}>
                        <span className="rt-chev">{rIcons.caret}</span>
                        <span className="rt-chapter-num">{c.num}.</span>
                        <span className="rt-chapter-title">{c.title}</span>
                      </button>
                    </td>
                    <td className="rt-muted">—</td>
                    <td className="rt-muted">{c.items.length} {c.items.length === 1 ? "item" : "items"}</td>
                    <td><b>{chapterScore.toFixed(1)}</b></td>
                    <td><b>{chapterActions}</b></td>
                  </tr>
                  {isOpen && c.items.map((it) => {
                    const st = scoreTypeFor(it);
                    const qt = questionTypeFor(it);
                    const sc = scoreFor(it);
                    const ac = actionsFor(it);
                    return (
                      <tr key={it.id} className="rt-tr-item">
                        <td className="rt-item-name">
                          <span className="rt-item-num">{it.num}</span>
                          <span>{it.title}</span>
                        </td>
                        <td><div className="rt-st-cell"><ScoreTypeChip kind={st} small /><span>{st}</span></div></td>
                        <td>
                          <span className="rt-qt-cell">
                            <span className="rt-qt-tag">Formal</span>
                            {qt && qt !== "Formal" && <span className={`rt-qt-tag rt-qt-${qt.toLowerCase()}`}>{qt}</span>}
                          </span>
                        </td>
                        <td className="rt-score">{sc.toFixed(1)}</td>
                        <td className="rt-actions-cell">{ac}</td>
                      </tr>
                    );
                  })}
                </React.Fragment>
              );
            })}
          </tbody>
        </table>
      </div>
    </section>
  );
}

function DistributionForQuestion({ item }) {
  const dist = syntheticDist(item);
  if (!dist) return null;
  const t = item.questionType;
  const gv = window.gwViews;
  if (!gv || !gv.RadioChart) return null;
  return (
    <div className="rt-q-chart">
      {t === "radio"    && <gv.RadioChart    item={item} dist={dist} />}
      {t === "rating"   && <gv.RatingChart   item={item} dist={dist} />}
      {t === "boolean"  && <gv.BooleanChart  item={item} dist={dist} />}
      {t === "text"     && <gv.TextResponses item={item} dist={dist} />}
      {t === "textarea" && <gv.TextareaResponses item={item} dist={dist} />}
    </div>
  );
}

/* =====================================================================
   Per-item result card — handles every item type
   ===================================================================== */
function QuestionResultCard({ chapter, item, gwViews }) {
  const [open, setOpen] = rUseState(true);
  const st = scoreTypeFor(item);
  const qt = questionTypeFor(item);

  const isQuestion = item.type === "question";
  const dist = isQuestion ? syntheticDist(item) : null;
  const avg  = isQuestion ? averageFromDist(item, dist) : 0;
  const max  = item.scale?.max || (item.questionType === "rating" ? 5 : 5);
  const health = isQuestion ? healthFromDist(item, dist) : 0;

  /* Helper to know whether to show the stat row (only when there's an
     average score concept). */
  const showAvg = isQuestion && (item.questionType === "rating" || item.questionType === "radio");
  const showHealth = isQuestion;

  /* Body — re-use the actual content viewers for content/media/evidence
     so the results tab mirrors what the completer saw. Question items
     get the per-type chart instead. */
  const renderBody = () => {
    if (!gwViews) return null;
    if (item.type === "content")  return <gwViews.ContentView  item={item} complete={true} onComplete={() => {}} />;
    if (item.type === "media")    return <gwViews.MediaView    item={item} complete={true} onComplete={() => {}} />;
    if (item.type === "evidence") return <gwViews.EvidenceView item={item} complete={true} onComplete={() => {}} />;
    return null;
  };

  return (
    <article className={`rt-q ${open ? "is-open" : ""} rt-q-type-${item.type}`}>
      <header className="rt-q-head" onClick={() => setOpen(o => !o)}>
        <div className="rt-q-meta">
          <div className="rt-q-eyebrow">Chapter {chapter.num}: {chapter.title}</div>
          <h3 className="rt-q-title">
            <span className="rt-q-num">{item.num}</span>
            <span>{item.title}</span>
          </h3>
          <div className="rt-q-tags">
            <span className="rt-qt-tag">Formal</span>
            {qt && qt !== "Formal" && <span className={`rt-qt-tag rt-qt-${qt.toLowerCase()}`}>{qt}</span>}
          </div>
        </div>
        <button className="rt-q-toggle" aria-expanded={open} aria-label={open ? "Collapse" : "Expand"}>
          <span className="rt-chev">{rIcons.expand}</span>
        </button>
      </header>

      {open && (
        <div className="rt-q-body">
          {/* Question stats — only meaningful for interactive questions */}
          {isQuestion && (showAvg || showHealth) && (
            <div className="rt-q-stats">
              {showAvg && (
                <div className="rt-q-stat">
                  <span className="rt-q-stat-icon rt-q-stat-blue">{rIcons.score}</span>
                  <div className="rt-q-stat-text">
                    <span className="rt-q-stat-lbl">Average score</span>
                    <span className="rt-q-stat-num">{avg.toFixed(2)} <span className="rt-q-stat-of">out of {max.toFixed(2)}</span></span>
                  </div>
                </div>
              )}
              {showHealth && (
                <div className="rt-q-stat">
                  <span className="rt-q-stat-icon rt-q-stat-green">{rIcons.compliance}</span>
                  <div className="rt-q-stat-text">
                    <span className="rt-q-stat-lbl">Health score</span>
                    <span className="rt-q-stat-num">{health}%</span>
                  </div>
                </div>
              )}
              <div className="rt-q-stat">
                <span className="rt-q-stat-icon rt-q-stat-grey">{rIcons.attendance}</span>
                <div className="rt-q-stat-text">
                  <span className="rt-q-stat-lbl">Responses</span>
                  <span className="rt-q-stat-num">{dist?.total || 0}</span>
                </div>
              </div>
            </div>
          )}

          {/* Body — content / media / evidence renders the actual content viewer */}
          {renderBody()}

          {/* Per-question-type chart */}
          {isQuestion && <DistributionForQuestion item={item} />}

          {/* AI summary only when there's a question (or any answered item) */}
          {isQuestion && <AiSummary item={item} />}

          {/* Session notes only on items that captured commentary */}
          {(isQuestion || (item.type === "media" && item.commentBox)) && (
            <SessionNotes item={item} />
          )}
        </div>
      )}
    </article>
  );
}

/* AI summary block — short synthesised paragraph keyed by the dist's
   leaning. Doesn't call Claude (rate-limit hostile per card). */
function AiSummary({ item }) {
  const seed = rHash(item.id);
  const lean = seed % 3;
  const text = lean === 0
    ? `Responses cluster around the positive bands. The team broadly agrees the foundations are in place — there's appetite to push further but no signal of widespread resistance.`
    : lean === 1
    ? `Sharply split. About a third are clearly behind it, another third sit on the fence, and a meaningful tail pushes back. Worth a follow-up conversation to understand the dissent.`
    : `Overwhelmingly skewed to the lower bands. Take this as a signal that the framing or the process itself needs revisiting before any individual action items.`;
  return (
    <div className="rt-q-ai">
      <div className="rt-q-ai-head">
        <span className="rt-q-ai-badge">{rIcons.sparkle} AI Summary</span>
      </div>
      <p className="rt-q-ai-body">{text}</p>
    </div>
  );
}

function SessionNotes({ item }) {
  const NOTES_SEED = [
    "\"I think our teams know, but they don't necessarily like it.\" \"Some of the teams actively pushing against it.\"",
    "\"From front-line, not everyone necessarily believes it is their accountability. They may call it out, but not necessarily their accountability.\" \"Helping leaders with further engaging in discussion when they get push-back and challenge on \"you are pushing me\"",
    "\"Teams may not have a clear understanding to identify the lower level hazards.\" On a journey here.",
    "50 — \"Still think half our workforce dont get this.\" >3000 odd people. Example shared of incident on-site with two females in the room and a comment made. Leader addressed. \"Bunch of people get it and some people don't.\"",
  ];
  return (
    <div className="rt-q-notes">
      <header className="rt-q-notes-head">Session Notes</header>
      <ul>
        {NOTES_SEED.map((n, i) => <li key={i}>{n}</li>)}
      </ul>
    </div>
  );
}

/* =====================================================================
   Results header
   ===================================================================== */
function ResultsHeader() {
  const [open, setOpen] = rUseState(false);
  return (
    <header className="rt-header">
      <div>
        <h2>Workshop results</h2>
        <p>Showing detailed results of each question.</p>
      </div>
      <div className="rt-header-actions">
        <div className="rt-dropdown">
          <button className="rt-btn" onClick={() => setOpen(o => !o)}>
            <span>Result options</span>
            {rIcons.expand}
          </button>
          {open && (
            <ul className="rt-dropdown-menu" onMouseLeave={() => setOpen(false)}>
              <li><button>{rIcons.download} Export as PDF</button></li>
              <li><button>{rIcons.download} Export as CSV</button></li>
              <li><button>Share read-only link</button></li>
              <li><button>Filter by chapter…</button></li>
            </ul>
          )}
        </div>
      </div>
    </header>
  );
}

/* =====================================================================
   Question overview — layout A: chapter rail + foldable sections
   ===================================================================== */
function QuestionOverviewRail({ chapters, gwViews }) {
  /* Track open state per chapter and the current rail-target */
  const [open, setOpen] = rUseState(() => new Set([chapters[0]?.id]));
  const [active, setActive] = rUseState(chapters[0]?.id);
  const containerRef = rUseRef(null);
  const sectionRefs = rUseRef({});

  const toggle = (id) => setOpen(prev => {
    const next = new Set(prev);
    next.has(id) ? next.delete(id) : next.add(id);
    return next;
  });

  const goTo = (id) => {
    setActive(id);
    setOpen(prev => { const n = new Set(prev); n.add(id); return n; });
    /* Defer so the section is mounted before we scroll */
    requestAnimationFrame(() => {
      const el = sectionRefs.current[id];
      if (!el) return;
      const rect = el.getBoundingClientRect();
      const offsetTop = rect.top + window.scrollY - 80; /* leave room for the workshop topbar */
      window.scrollTo({ top: offsetTop, behavior: "smooth" });
    });
  };

  /* Per-chapter score roll-up (reuse the helper from ScoreBreakdownTable) */
  const chapterScore = (c) => c.items.length
    ? Math.round((c.items.reduce((s, it) => s + scoreFor(it), 0) / c.items.length) * 10) / 10
    : 0;

  return (
    <section className="rt-section">
      <header className="rt-section-head">
        <h2>Question overview &amp; scores</h2>
        <p>View details of each question with results from workshop.</p>
      </header>
      <div className="rt-rail-layout" ref={containerRef}>
        <aside className="rt-rail" aria-label="Jump to chapter">
          <div className="rt-rail-head">Chapters</div>
          <ul className="rt-rail-list">
            {chapters.map((c) => {
              const isActive = active === c.id;
              const isOpen = open.has(c.id);
              const sc = chapterScore(c);
              return (
                <li key={c.id}>
                  <button
                    className={`rt-rail-item ${isActive ? "is-active" : ""} ${isOpen ? "is-open" : ""}`}
                    onClick={() => goTo(c.id)}
                  >
                    <span className="rt-rail-num">{c.num}</span>
                    <span className="rt-rail-text">
                      <span className="rt-rail-title">{c.title}</span>
                      <span className="rt-rail-meta">{c.items.length} {c.items.length === 1 ? "item" : "items"} · score {sc.toFixed(1)}</span>
                    </span>
                  </button>
                </li>
              );
            })}
          </ul>
        </aside>

        <div className="rt-rail-body">
          {chapters.map((c) => {
            const isOpen = open.has(c.id);
            const sc = chapterScore(c);
            return (
              <section
                key={c.id}
                className={`rt-chapter-section ${isOpen ? "is-open" : ""}`}
                ref={(el) => { if (el) sectionRefs.current[c.id] = el; }}
              >
                <button
                  className="rt-chapter-section-head"
                  onClick={() => toggle(c.id)}
                  aria-expanded={isOpen}
                >
                  <span className="rt-chapter-section-num">{c.num}</span>
                  <span className="rt-chapter-section-text">
                    <span className="rt-chapter-section-title">{c.title}</span>
                    <span className="rt-chapter-section-meta">{c.items.length} {c.items.length === 1 ? "item" : "items"} · score {sc.toFixed(1)}</span>
                  </span>
                  <span className="rt-chapter-section-chev">{rIcons.caret}</span>
                </button>
                {isOpen && (
                  <div className="rt-chapter-section-items">
                    {c.items.map((item) => (
                      <QuestionResultCard key={item.id} chapter={c} item={item} gwViews={gwViews} />
                    ))}
                  </div>
                )}
              </section>
            );
          })}
        </div>
      </div>
    </section>
  );
}

/* =====================================================================
   Question overview — layout C: chapter tabs
   ===================================================================== */
function QuestionOverviewTabs({ chapters, gwViews }) {
  const [activeId, setActiveId] = rUseState(chapters[0]?.id);
  const activeChapter = chapters.find(c => c.id === activeId) || chapters[0];
  const chapterScore = (c) => c.items.length
    ? Math.round((c.items.reduce((s, it) => s + scoreFor(it), 0) / c.items.length) * 10) / 10
    : 0;

  return (
    <section className="rt-section">
      <header className="rt-section-head">
        <h2>Question overview &amp; scores</h2>
        <p>View details of each question with results from workshop. Switch chapters with the tabs above.</p>
      </header>
      <div className="rt-tabstrip" role="tablist">
        {chapters.map((c) => {
          const isActive = c.id === activeId;
          return (
            <button
              key={c.id}
              role="tab"
              aria-selected={isActive}
              className={`rt-chapter-tab ${isActive ? "is-active" : ""}`}
              onClick={() => setActiveId(c.id)}
            >
              <span className="rt-chapter-tab-num">{c.num}</span>
              <span className="rt-chapter-tab-text">
                <span className="rt-chapter-tab-title">{c.title}</span>
                <span className="rt-chapter-tab-meta">{c.items.length} · {chapterScore(c).toFixed(1)}</span>
              </span>
            </button>
          );
        })}
      </div>
      <div className="rt-chapter-pane">
        {activeChapter && activeChapter.items.map((item) => (
          <QuestionResultCard key={item.id} chapter={activeChapter} item={item} gwViews={gwViews} />
        ))}
      </div>
    </section>
  );
}

/* =====================================================================
   Top-level revamped Results tab
   ===================================================================== */
function ResultsTabRevamped({ layout = "rail" }) {
  const chapters = window.GW_CHAPTERS;
  const actions  = window.GW_ACTIONS || [];
  const gwViews  = window.gwViews;

  const stats = rUseMemo(() => {
    /* Attendance — derive from the polls that have session data; fall
       back to plausible defaults. */
    let participants = 320;
    let responses = 0;
    for (const c of chapters) for (const it of c.items) {
      if (it.session) responses = Math.max(responses, it.session.responded || 0);
    }
    if (responses === 0) responses = 80;

    /* Avg score across all items */
    const allItems = chapters.flatMap(c => c.items);
    const avgScore = allItems.length
      ? allItems.reduce((s, it) => s + scoreFor(it), 0) / allItems.length
      : 0;

    /* Health score (%) — average across question items only */
    const qItems = allItems.filter(it => it.type === "question");
    const allHealth = qItems.length
      ? Math.round(qItems.reduce((s, it) => s + healthScoreFromItem(it), 0) / qItems.length)
      : 0;

    /* Per score-type grade */
    const byType = { Understanding: [], Compliance: [], Performance: [] };
    for (const it of allItems) byType[scoreTypeFor(it)].push(scoreFor(it));
    const grades = {
      Understanding: gradeFor(byType.Understanding.reduce((s, n) => s + n, 0) / Math.max(1, byType.Understanding.length)),
      Compliance:    gradeFor(byType.Compliance.reduce((s, n) => s + n, 0) / Math.max(1, byType.Compliance.length)),
      Performance:   gradeFor(byType.Performance.reduce((s, n) => s + n, 0) / Math.max(1, byType.Performance.length)),
    };

    /* Action bucket counts — use GW_ACTIONS' priority field if present */
    const actCounts = { opportunity: 0, action: 0, feedback: 0 };
    actions.forEach((a) => {
      const p = (a.priority || "med");
      if (p === "high") actCounts.opportunity++;
      else if (p === "low") actCounts.feedback++;
      else actCounts.action++;
    });
    /* Backfill to match the screenshot numbers if zeros */
    if (actCounts.opportunity === 0) actCounts.opportunity = 3;
    if (actCounts.action === 0)      actCounts.action = 1;
    if (actCounts.feedback === 0)    actCounts.feedback = 5;

    return { participants, responses, avgScore, healthScore: allHealth, grades, actions: actCounts };
  }, [chapters, actions]);

  /* Pairs of (chapter, item) — flattened (used only if a future
     "all" layout shows the whole list). */
  const allPairs = rUseMemo(() => {
    const out = [];
    for (const c of chapters) for (const it of c.items) out.push({ chapter: c, item: it });
    return out;
  }, [chapters]);

  return (
    <div className="rt-root">
      <ResultsHeader />
      <ResultsStatGrid stats={stats} />
      <ScoreBreakdownTable chapters={chapters} />
      {layout === "tabs"
        ? <QuestionOverviewTabs chapters={chapters} gwViews={gwViews} />
        : <QuestionOverviewRail chapters={chapters} gwViews={gwViews} />}
    </div>
  );
}

window.ResultsTabRevamped = ResultsTabRevamped;
