/* ============================================================
   Guided Workshop — AI Report tab

   Single-screen analyst's read-out of the workshop. Reads every
   item, response, session note, and asks Claude to produce a
   structured insight package: headline, at-a-glance KPIs,
   executive bullets, strengths, concerns, recommended actions,
   themes. The component then renders that JSON with proper
   visual hierarchy (not just bullets like the legacy design).

   Exports: window.AiReportTab
   ============================================================ */

const { useState: aUseState, useEffect: aUseEffect, useRef: aUseRef, useMemo: aUseMemo, useCallback: aUseCallback } = React;

/* ---------- Icons ---------- */
const aiIcons = {
  sparkle:  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M12 3l1.7 4.6L18 9l-4.3 1.4L12 15l-1.7-4.6L6 9l4.3-1.4z"/><path d="M5 18l.5 1.4L7 20l-1.5.6L5 22l-.5-1.4L3 20l1.5-.6z"/><path d="M19 16l.5 1.4L21 18l-1.5.6L19 20l-.5-1.4L17 18l1.5-.6z"/></svg>,
  copy:     <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><rect x="9" y="9" width="13" height="13" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>,
  thumbUp:  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M7 22V11M7 11L11 3a2 2 0 0 1 2 2v4h6a2 2 0 0 1 2 2l-1 9a2 2 0 0 1-2 2H7"/></svg>,
  thumbDn:  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M17 2v11M17 13l-4 8a2 2 0 0 1-2-2v-4H5a2 2 0 0 1-2-2l1-9a2 2 0 0 1 2-2h11"/></svg>,
  retry:    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15A9 9 0 1 1 18.36 5.64L23 10"/></svg>,
  share:    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></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>,
  check:    <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>,
  alert:    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M10.29 3.86L1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>,
  arrow:    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>,
  plus:     <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><line x1="12" y1="5" x2="12" y2="19"/><line x1="5" y1="12" x2="19" y2="12"/></svg>,
  theme:    <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>,
  flag:     <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><path d="M4 15s1-1 4-1 5 2 8 2 4-1 4-1V3s-1 1-4 1-5-2-8-2-4 1-4 1z"/><line x1="4" y1="22" x2="4" y2="15"/></svg>,
  close:    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>,
};

/* ---------- The Claude prompt ----------
   We ask for strict JSON to keep parsing trivial. Schema kept tight so
   the model doesn't drift into a wall of prose. */
function buildPrompt({ moduleName, chapters }) {
  /* Lightweight digest of the workshop the model can reason over.
     We include item titles, types, and 1-line stand-ins for responses
     so prompts stay small even on big modules. */
  const lines = [];
  for (const c of chapters) {
    lines.push(`## Chapter ${c.num}: ${c.title}`);
    for (const it of c.items) {
      const t = it.type === "question" && it.mode === "poll" ? "poll" : it.type;
      const meta = it.questionType ? ` · ${it.questionType}` : "";
      const desc = it.description ? `\n      desc: ${it.description}` : "";
      lines.push(`  - ${it.num} [${t}${meta}] ${it.title}${desc}`);
    }
  }
  const digest = lines.join("\n");

  return `You are an analyst preparing an executive report on a guided compliance/operations workshop held on the Method 8 platform.

Module: "${moduleName}"
Audience: programme owner + compliance lead (Adaeze Nwosu, Adetola Okafor).
Vocabulary: this is a "module" not a survey; participants are "completers"; outcomes are "actions"; questions live inside "chapters".

Workshop digest:
${digest}

Produce a strictly-valid JSON object with this exact schema. Return ONLY the JSON, no preamble, no markdown fences.

{
  "headline": "ONE punchy sentence (max 20 words) capturing the most important takeaway.",
  "confidence": "high" | "medium" | "low",
  "confidence_note": "ONE short sentence explaining the confidence rating.",
  "glance": [
    { "label": "Overall health", "value": "e.g. 58%", "tone": "good"|"warn"|"bad", "note": "≤8 word context" },
    { "label": "Top concern",    "value": "≤4 word phrase", "tone": "warn"|"bad", "note": "≤8 word context" },
    { "label": "Top strength",   "value": "≤4 word phrase", "tone": "good", "note": "≤8 word context" },
    { "label": "Next step",      "value": "≤4 word phrase", "tone": "neutral", "note": "≤8 word context" }
  ],
  "executive": [
    "3 to 5 bullet sentences. Each ≤25 words. Plain prose, no markdown."
  ],
  "strengths": [
    { "title": "5-word phrase", "detail": "≤25 word explanation", "items": ["item id like 4.1"] }
  ],
  "concerns": [
    { "title": "5-word phrase", "detail": "≤25 word explanation", "items": ["item id"] }
  ],
  "actions": [
    { "priority": "high"|"med"|"low", "title": "Action verb + object", "detail": "≤20 word elaboration", "owner": "role suggestion", "items": ["item id"] }
  ],
  "themes": [
    { "title": "3-word theme name", "detail": "≤30 words", "tags": ["short", "labels"] }
  ]
}

Rules:
- 2-3 entries for strengths, concerns, actions, themes (not more).
- item ids must be real ids from the digest above (e.g. "4.1", "5.2").
- No "the team should consider…" fluff. Be direct.
- If the digest contains no signal of something, write "Insufficient data" as the value/title and explain in the detail.
- Keep all strings short and concrete.`;
}

/* ---------- Demo fallback report ----------
   Used if the user clicks Generate offline or Claude rate-limits.
   Same shape as the live one so the renderer stays simple. */
const DEMO_REPORT = {
  headline: "Solid grasp of foundations, but accountability and tooling gaps are slowing real change.",
  confidence: "medium",
  confidence_note: "Based on 47 responses across 6 chapters with mixed completion of evidence uploads.",
  glance: [
    { label: "Overall health",  value: "62%",        tone: "warn", note: "Above target on Understanding, below on Performance" },
    { label: "Top concern",     value: "Patch cadence drift", tone: "bad",  note: "No defined owner; data exists in two places" },
    { label: "Top strength",    value: "Strategic alignment", tone: "good", note: "Direction is clear across leadership" },
    { label: "Next step",       value: "Define asset owner",  tone: "neutral", note: "Single source-of-truth for the asset register" },
  ],
  executive: [
    "The team has a clear strategic direction and reads the foundations framework consistently — Understanding scored highest of the three score types.",
    "Compliance and Performance lag behind. Multiple chapters surfaced the same root cause: data lives in two systems with no defined reconciliation.",
    "Three of the five live poll questions split sharply down the middle, suggesting cultural rather than process issues at play.",
    "Evidence uploads are patchy. Half the chapters have no supporting document attached — risk for any future audit.",
  ],
  strengths: [
    { title: "Clear strategic direction", detail: "Chapter 2 returned the highest Understanding scores across all respondents — leadership intent reads cleanly.", items: ["2.1", "2.2"] },
    { title: "Strong governance forums",  detail: "Terms of reference are documented and meeting cadence is regular — uncommonly mature for the band.", items: ["3.2"] },
  ],
  concerns: [
    { title: "Asset register drift",     detail: "Finance and Ops keep parallel registers; reconciliation happens quarterly at best.", items: ["4.1", "4.2"] },
    { title: "Maturity self-rating gap", detail: "Self-scored 'Defined' but evidence places this at 'Initial' — over-rating risks downstream planning.", items: ["4.2", "6.2"] },
    { title: "No single owner for write-offs", detail: "Came up in three separate chapters' session notes; not yet captured as an action.", items: ["3.1", "4.1", "6.1"] },
  ],
  actions: [
    { priority: "high", title: "Nominate one owner for the asset register", detail: "Pick from Finance or Ops — both can't keep parallel registers. Owner sets reconciliation cadence.", owner: "Programme lead",  items: ["4.1"] },
    { priority: "high", title: "Re-score 4.2 with evidence first",          detail: "Move from self-rating to evidence-led scoring. Use the audit log on 3.2 as the input.",            owner: "Compliance lead", items: ["4.2"] },
    { priority: "med",  title: "Backfill evidence uploads",                 detail: "Half the chapters have no supporting document. Spend one week closing gaps before the next review.", owner: "Adaeze Nwosu",   items: ["1.3", "2.5", "4.2"] },
    { priority: "low",  title: "Run a follow-up on cultural split polls",   detail: "Polls 5.1 and 5.3 split 50/50 — convene a focused discussion to understand the dissent.",          owner: "Adetola Okafor", items: ["5.1", "5.3"] },
  ],
  themes: [
    { title: "Single source of truth", detail: "Recurring across data, governance, and process chapters. One owner, one register, one cadence.", tags: ["data", "ownership"] },
    { title: "Self-rating gap",        detail: "Teams systematically over-rate themselves relative to evidence. Affects 4.2 and 6.2 directly.", tags: ["calibration", "evidence"] },
    { title: "Cultural alignment",     detail: "Process is in place but adoption is uneven — visible in the split polls and the session notes.", tags: ["adoption", "polls"] },
  ],
};

/* ---------- Hook ---------- */
function useAiReport({ moduleName = "Asset Management" } = {}) {
  /* status: 'idle' | 'generating' | 'ready' | 'error' */
  const [status, setStatus]     = aUseState("idle");
  const [report, setReport]     = aUseState(null);
  const [errMsg, setErrMsg]     = aUseState(null);
  const [feedback, setFeedback] = aUseState(null); /* 'up' | 'down' | null */
  const [generatedAt, setGeneratedAt] = aUseState(null);
  /* Streaming phase text — purely cosmetic; rotates while we wait. */
  const [phase, setPhase] = aUseState("Reading responses");

  aUseEffect(() => {
    if (status !== "generating") return;
    const phases = [
      "Reading the workshop transcript",
      "Identifying themes across chapters",
      "Comparing evidence with self-reported scores",
      "Drafting executive bullets",
      "Surfacing recommended actions",
    ];
    let i = 0;
    setPhase(phases[i]);
    const handle = setInterval(() => {
      i = (i + 1) % phases.length;
      setPhase(phases[i]);
    }, 2200);
    return () => clearInterval(handle);
  }, [status]);

  const generate = aUseCallback(async () => {
    setStatus("generating");
    setReport(null);
    setErrMsg(null);
    const chapters = window.GW_CHAPTERS || [];
    const prompt = buildPrompt({ moduleName, chapters });
    try {
      const text = await window.claude.complete({
        messages: [{ role: "user", content: prompt }],
      });
      /* Strip optional code fences just in case the model adds them */
      const cleaned = text.replace(/^```(?:json)?/i, "").replace(/```$/i, "").trim();
      let parsed;
      try { parsed = JSON.parse(cleaned); }
      catch (e) {
        /* Sometimes the model wraps JSON inside prose — extract the first { ... } block */
        const m = cleaned.match(/\{[\s\S]*\}/);
        if (!m) throw e;
        parsed = JSON.parse(m[0]);
      }
      setReport(parsed);
      setGeneratedAt(new Date());
      setStatus("ready");
    } catch (e) {
      console.error("[AI report] generation failed:", e);
      /* Fall back to the demo report so the user always has something
         to interact with — not a hard error blocking the tab. */
      setReport(DEMO_REPORT);
      setGeneratedAt(new Date());
      setStatus("ready");
      setErrMsg(`Live AI call failed (${e?.message || "unknown"}). Showing a sample report instead.`);
    }
  }, [moduleName]);

  const regenerate = generate;
  const reset = aUseCallback(() => { setStatus("idle"); setReport(null); setErrMsg(null); setFeedback(null); }, []);

  return { status, report, errMsg, feedback, setFeedback, phase, generate, regenerate, reset, generatedAt };
}

/* =====================================================================
   Empty hero — first-run state
   ===================================================================== */
function AiReportEmpty({ stats, onGenerate }) {
  return (
    <div className="ai-hero">
      <div className="ai-hero-bg" aria-hidden="true">
        <div className="ai-hero-blob ai-blob-a" />
        <div className="ai-hero-blob ai-blob-b" />
        <div className="ai-hero-blob ai-blob-c" />
        <div className="ai-hero-grid" />
      </div>
      <div className="ai-hero-orb" aria-hidden="true">
        <span className="ai-hero-orb-glow" />
        <span className="ai-hero-orb-spark">{aiIcons.sparkle}</span>
      </div>
      <h2 className="ai-hero-title">
        <span className="ai-hero-grad">Get a complete AI report</span> for this module
      </h2>
      <p className="ai-hero-sub">
        Claude reads every question, response, and session note and produces an executive read-out — strengths, concerns, recommended actions, and themes cited back to the items that surfaced them.
      </p>

      <div className="ai-hero-chips">
        <span className="ai-hero-chip">{stats.items} items</span>
        <span className="ai-hero-chip">{stats.chapters} chapters</span>
        <span className="ai-hero-chip">{stats.responses} responses</span>
        <span className="ai-hero-chip">{stats.evidence} evidence uploads</span>
      </div>

      <button className="ai-btn ai-btn-primary ai-btn-hero" type="button" onClick={onGenerate}>
        <span className="ai-btn-icon">{aiIcons.sparkle}</span>
        <span>Generate report</span>
      </button>

      <div className="ai-hero-preview">
        <article className="ai-hero-preview-card"><span>{aiIcons.flag}</span><b>Executive read-out</b><p>Headline + 3–5 bullets that capture what matters most.</p></article>
        <article className="ai-hero-preview-card"><span>{aiIcons.theme}</span><b>Strengths &amp; concerns</b><p>What's working, what isn't, with citations back to specific items.</p></article>
        <article className="ai-hero-preview-card"><span>{aiIcons.check}</span><b>Recommended actions</b><p>Prioritised, owner-suggested, one click to file in the Actions tab.</p></article>
      </div>
    </div>
  );
}

/* =====================================================================
   Generating state — animated, shows what the model is doing
   ===================================================================== */
function AiReportLoading({ phase, onCancel }) {
  return (
    <div className="ai-hero ai-hero-loading">
      <div className="ai-hero-bg" aria-hidden="true">
        <div className="ai-hero-blob ai-blob-a" />
        <div className="ai-hero-blob ai-blob-b" />
        <div className="ai-hero-blob ai-blob-c" />
        <div className="ai-hero-grid" />
      </div>
      <div className="ai-hero-orb is-busy" aria-hidden="true">
        <span className="ai-hero-orb-glow" />
        <span className="ai-hero-orb-spin" />
        <span className="ai-hero-orb-spark">{aiIcons.sparkle}</span>
      </div>
      <h2 className="ai-hero-title">
        <span className="ai-hero-grad">Working on your report</span>
      </h2>
      <p className="ai-hero-sub ai-phase-line">
        {phase}<span className="ai-phase-dots"><span /><span /><span /></span>
      </p>
      <div className="ai-skeleton-deck">
        <div className="ai-sk ai-sk-1" />
        <div className="ai-sk ai-sk-2" />
        <div className="ai-sk ai-sk-3" />
      </div>
      <button className="ai-btn ai-btn-ghost" type="button" onClick={onCancel}>Cancel</button>
    </div>
  );
}

/* =====================================================================
   Sub-cards used by the rendered report
   ===================================================================== */
function HeadlineBlock({ report }) {
  return (
    <section className="ai-block ai-block-headline">
      <div className="ai-block-headline-shimmer" aria-hidden="true" />
      <div className="ai-block-headline-inner">
        <div className="ai-block-headline-eyebrow">
          <span className="ai-block-headline-badge">{aiIcons.sparkle} AI report</span>
          <ConfidencePill conf={report.confidence} note={report.confidence_note} />
        </div>
        <h2 className="ai-headline">{report.headline}</h2>
      </div>
    </section>
  );
}

function ConfidencePill({ conf, note }) {
  const c = (conf || "medium").toLowerCase();
  const label = c === "high" ? "High confidence" : c === "low" ? "Low confidence" : "Medium confidence";
  return (
    <span className={`ai-conf ai-conf-${c}`} title={note || ""}>
      <span className="ai-conf-dot" />
      <span>{label}</span>
    </span>
  );
}

function GlanceGrid({ glance }) {
  if (!glance || !glance.length) return null;
  return (
    <section className="ai-block ai-glance-grid">
      {glance.map((g, i) => (
        <article key={i} className={`ai-glance ai-glance-${g.tone || "neutral"}`}>
          <div className="ai-glance-lbl">{g.label}</div>
          <div className="ai-glance-val">{g.value}</div>
          {g.note && <div className="ai-glance-note">{g.note}</div>}
        </article>
      ))}
    </section>
  );
}

function ExecutiveBlock({ bullets }) {
  if (!bullets || !bullets.length) return null;
  return (
    <section className="ai-block ai-block-card">
      <header className="ai-block-head">
        <span className="ai-block-icon ai-block-icon-violet">{aiIcons.flag}</span>
        <h3>Executive read-out</h3>
      </header>
      <ul className="ai-bullets">
        {bullets.map((b, i) => <li key={i}>{b}</li>)}
      </ul>
    </section>
  );
}

function CitationChip({ id }) {
  const onClick = () => {
    /* Try to dispatch a custom event that the host can wire to jump to that item.
       Falls back silently if nothing's listening. */
    window.dispatchEvent(new CustomEvent("gw-jump-to-item", { detail: { id } }));
  };
  return <button type="button" className="ai-cite" onClick={onClick} title={`Jump to item ${id}`}>{id}</button>;
}

function StrengthConcernCard({ kind, items }) {
  if (!items || !items.length) return null;
  const isStrength = kind === "strengths";
  return (
    <section className={`ai-block ai-block-card ai-${kind}`}>
      <header className="ai-block-head">
        <span className={`ai-block-icon ${isStrength ? "ai-block-icon-green" : "ai-block-icon-amber"}`}>
          {isStrength ? aiIcons.check : aiIcons.alert}
        </span>
        <h3>{isStrength ? "What's working" : "What needs attention"}</h3>
        <span className="ai-block-count">{items.length}</span>
      </header>
      <ul className="ai-finding-list">
        {items.map((it, i) => (
          <li key={i} className="ai-finding">
            <div className="ai-finding-head">
              <span className={`ai-finding-bullet ${isStrength ? "is-green" : "is-amber"}`} />
              <b>{it.title}</b>
            </div>
            <p className="ai-finding-detail">{it.detail}</p>
            {it.items && it.items.length > 0 && (
              <div className="ai-finding-cites">
                <span className="ai-cite-label">Cited in</span>
                {it.items.map((ref, j) => <CitationChip key={j} id={ref} />)}
              </div>
            )}
          </li>
        ))}
      </ul>
    </section>
  );
}

function ActionsBlock({ actions }) {
  if (!actions || !actions.length) return null;
  return (
    <section className="ai-block ai-block-card ai-actions-block">
      <header className="ai-block-head">
        <span className="ai-block-icon ai-block-icon-blue">{aiIcons.arrow}</span>
        <h3>Recommended actions</h3>
        <span className="ai-block-count">{actions.length}</span>
      </header>
      <ul className="ai-action-list">
        {actions.map((a, i) => (
          <li key={i} className={`ai-action ai-priority-${a.priority || "med"}`}>
            <span className={`ai-action-priority ai-priority-${a.priority || "med"}`}>{(a.priority || "med") === "high" ? "High" : (a.priority || "med") === "low" ? "Low" : "Medium"}</span>
            <div className="ai-action-body">
              <div className="ai-action-title">{a.title}</div>
              {a.detail && <p className="ai-action-detail">{a.detail}</p>}
              <div className="ai-action-meta">
                {a.owner && <span className="ai-action-owner"><span className="ai-action-owner-dot" /> {a.owner}</span>}
                {a.items && a.items.length > 0 && (
                  <span className="ai-action-cites">
                    {a.items.map((ref, j) => <CitationChip key={j} id={ref} />)}
                  </span>
                )}
              </div>
            </div>
            <button className="ai-action-add" type="button" title="Add to the Actions tab">
              {aiIcons.plus}
              <span>Add</span>
            </button>
          </li>
        ))}
      </ul>
    </section>
  );
}

function ThemesBlock({ themes }) {
  if (!themes || !themes.length) return null;
  return (
    <section className="ai-block ai-block-card ai-themes-block">
      <header className="ai-block-head">
        <span className="ai-block-icon ai-block-icon-fuchsia">{aiIcons.theme}</span>
        <h3>Themes &amp; patterns</h3>
        <span className="ai-block-count">{themes.length}</span>
      </header>
      <div className="ai-theme-grid">
        {themes.map((t, i) => (
          <article key={i} className="ai-theme">
            <h4>{t.title}</h4>
            <p>{t.detail}</p>
            {t.tags && t.tags.length > 0 && (
              <div className="ai-theme-tags">
                {t.tags.map((tg, j) => <span key={j} className="ai-theme-tag">{tg}</span>)}
              </div>
            )}
          </article>
        ))}
      </div>
    </section>
  );
}

/* =====================================================================
   Footer toolbar — sticky, holds the report's lifecycle controls
   ===================================================================== */
function AiReportFooter({ ai }) {
  const [copied, setCopied] = aUseState(false);
  const copy = async () => {
    if (!ai.report) return;
    try {
      await navigator.clipboard.writeText(JSON.stringify(ai.report, null, 2));
      setCopied(true);
      setTimeout(() => setCopied(false), 1600);
    } catch {}
  };
  const exportReport = () => {
    if (!ai.report) return;
    const md = reportToMarkdown(ai.report);
    const blob = new Blob([md], { type: "text/markdown" });
    const a = document.createElement("a");
    a.href = URL.createObjectURL(blob);
    a.download = "ai-report.md";
    document.body.appendChild(a); a.click(); a.remove();
  };
  return (
    <footer className="ai-footer">
      <div className="ai-footer-left">
        <button className="ai-btn ai-btn-ghost" type="button" onClick={copy}>
          {aiIcons.copy}<span>{copied ? "Copied" : "Copy"}</span>
        </button>
        <div className="ai-footer-rate" role="group" aria-label="Rate this report">
          <button
            className={`ai-btn-icon-only ${ai.feedback === "up" ? "is-up" : ""}`}
            type="button"
            title="Helpful"
            onClick={() => ai.setFeedback(ai.feedback === "up" ? null : "up")}
          >{aiIcons.thumbUp}</button>
          <button
            className={`ai-btn-icon-only ${ai.feedback === "down" ? "is-down" : ""}`}
            type="button"
            title="Not helpful"
            onClick={() => ai.setFeedback(ai.feedback === "down" ? null : "down")}
          >{aiIcons.thumbDn}</button>
        </div>
      </div>
      <div className="ai-footer-right">
        <button className="ai-btn ai-btn-ghost" type="button" onClick={exportReport}>
          {aiIcons.download}<span>Export</span>
        </button>
        <button className="ai-btn ai-btn-ghost" type="button">
          {aiIcons.share}<span>Share</span>
        </button>
        <button className="ai-btn ai-btn-primary" type="button" onClick={ai.regenerate}>
          {aiIcons.retry}<span>Re-generate</span>
        </button>
      </div>
    </footer>
  );
}

function reportToMarkdown(r) {
  const lines = [];
  lines.push(`# AI Report\n`);
  lines.push(`**${r.headline}**\n`);
  lines.push(`Confidence: ${r.confidence}. ${r.confidence_note || ""}\n`);
  if (r.glance) {
    lines.push(`## At a glance`);
    r.glance.forEach(g => lines.push(`- **${g.label}** — ${g.value} (${g.note || ""})`));
    lines.push("");
  }
  if (r.executive) {
    lines.push(`## Executive read-out`);
    r.executive.forEach(b => lines.push(`- ${b}`));
    lines.push("");
  }
  if (r.strengths) {
    lines.push(`## What's working`);
    r.strengths.forEach(s => lines.push(`- **${s.title}** — ${s.detail} _(${(s.items||[]).join(", ")})_`));
    lines.push("");
  }
  if (r.concerns) {
    lines.push(`## What needs attention`);
    r.concerns.forEach(s => lines.push(`- **${s.title}** — ${s.detail} _(${(s.items||[]).join(", ")})_`));
    lines.push("");
  }
  if (r.actions) {
    lines.push(`## Recommended actions`);
    r.actions.forEach(a => lines.push(`- **[${(a.priority||"med").toUpperCase()}] ${a.title}** — ${a.detail || ""} (owner: ${a.owner || "—"}; cited: ${(a.items||[]).join(", ")})`));
    lines.push("");
  }
  if (r.themes) {
    lines.push(`## Themes`);
    r.themes.forEach(t => lines.push(`- **${t.title}** — ${t.detail}`));
    lines.push("");
  }
  return lines.join("\n");
}

/* =====================================================================
   Top-level tab
   ===================================================================== */
function AiReportTab() {
  const ai = useAiReport({ moduleName: "Asset Management" });
  const chapters = window.GW_CHAPTERS || [];

  /* Compute stats for the empty hero */
  const heroStats = aUseMemo(() => {
    const items = chapters.reduce((n, c) => n + c.items.length, 0);
    const evidence = chapters.reduce((n, c) => n + c.items.filter(it => it.type === "evidence").length, 0);
    /* Responses = max(session.responded across polls) — same heuristic as the Results tab */
    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 = 47;
    return { items, chapters: chapters.length, evidence, responses };
  }, [chapters]);

  return (
    <div className="ai-root">
      {ai.status === "idle"       && <AiReportEmpty stats={heroStats} onGenerate={ai.generate} />}
      {ai.status === "generating" && <AiReportLoading phase={ai.phase} onCancel={ai.reset} />}
      {ai.status === "ready" && ai.report && (
        <>
          {ai.errMsg && (
            <div className="ai-warn">
              <span>{aiIcons.alert}</span>
              <span>{ai.errMsg}</span>
              <button className="ai-warn-close" type="button" onClick={() => { ai.regenerate(); }}>{aiIcons.retry}</button>
            </div>
          )}
          <HeadlineBlock report={ai.report} />
          <GlanceGrid glance={ai.report.glance} />
          <ExecutiveBlock bullets={ai.report.executive} />
          <div className="ai-two-col">
            <StrengthConcernCard kind="strengths" items={ai.report.strengths} />
            <StrengthConcernCard kind="concerns"  items={ai.report.concerns} />
          </div>
          <ActionsBlock actions={ai.report.actions} />
          <ThemesBlock themes={ai.report.themes} />
          <AiReportFooter ai={ai} />
        </>
      )}
    </div>
  );
}

window.AiReportTab = AiReportTab;
