// REPORT view — per-LLM breakdown is the hero.

// What each cluster actually measures, in one sentence. Surfaced as a
// caption row under the cluster name so the table stops being a wall of
// numbers without context. Sourced from the cluster definitions in
// engine/components.js.
const CLUSTER_DESC = {
  semanticRelevance:    'Does the page answer the queries it should? Embedding similarity + heading-section coherence.',
  intentCoverage:       'Coverage across definition / mechanics / alternatives / follow-up facets — does it answer the WHOLE question or one slice?',
  trustReliability:     'Numeric claims with sources, confident phrasing, consistent terminology — what makes an LLM treat this as authoritative.',
  contentClarity:       'Sentence length, paragraph rhythm, concrete examples. Per-language readability formula.',
  entityAuthority:      'Schema, Wikipedia, external profiles, brand disambiguation. Can an LLM tell which entity this page is about?',
  citationPotential:    'Standalone quotable lines, stats, tables, FAQ pairs. The shape of content LLMs lift verbatim.',
  structureReadability: 'Schema.org blocks, clean HTML, robots access, llms.txt. The crawlability layer.',
  freshness:            'Last-Modified header, ISO dateModified in JSON-LD, current-year references. Perplexity weights this 4× more than Claude does.',
  crossReference:       'Reddit / GitHub / Wikipedia / YouTube / G2 mentions. Off-page signal that you exist outside your own site.',
  toolActionability:    'Pricing, sign-up, API docs, server-rendered. Does the page give the user something to DO?'
};

// What each platform-score column means, used in a tooltip and short caption.
const PLATFORM_DESC = {
  chatgpt:    'Wikipedia + structured references + brand reputation dominate (Bing-backed, E-E-A-T heavy).',
  claude:     'Long-form coherence, copyright hygiene, citation discipline. Evergreen bias.',
  gemini:     'Schema.org + entity authority + Knowledge Graph anchoring. Cleanly parseable HTML.',
  perplexity: 'Freshness-driven (82% of citations under 30 days) + quotable spans + lexical match.',
  googleAio:  'Reddit + community signals + Knowledge Graph + featured-snippet format.',
  deepseek:   'Dense-embedding semantic match + clean technical prose + markdown/code blocks.'
};

function Report({ data }) {
  const composite = data.score;

  // Claude-written recommendations. The /api/recommendations endpoint takes
  // the heuristic fixes and rewrites them as concrete, paste-able prose
  // (title + rewrite + why). Was previously unwired in the React tree —
  // user reported "tavsiyeler nerede?" because the heuristic FIX LIST was
  // the only thing on the page and didn't read as advice.
  const [recs, setRecs] = React.useState({ state: 'idle', items: [], provider: '', note: '' });
  React.useEffect(() => {
    // Bail when we have no domain yet (first paint shows the demo dataset).
    if (!data?.domain || !data?.fixes?.length) return;
    let cancelled = false;
    setRecs({ state: 'loading', items: [], provider: '', note: '' });
    (async () => {
      try {
        const r = await fetch('/api/recommendations', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            domain: data.domain,
            brand: data.brand || data.domain,
            // Shape the heuristic fixes into what /api/recommendations expects
            fixes: data.fixes.slice(0, 6).map(f => ({ component: f.cluster, impact: f.impact, text: `${f.title}. ${f.detail}` })),
            components: Object.fromEntries((data.clusters || []).map(c => [c.id, { score: c.score, label: c.label }])),
            lang: (document.documentElement.lang || 'en').slice(0, 2)
          })
        });
        const j = await r.json();
        if (cancelled) return;
        if (!j?.ok) throw new Error(j?.error || 'recs failed');
        setRecs({ state: 'ready', items: j.items || [], provider: j.provider || '', note: j.note || '' });
      } catch (e) {
        if (cancelled) return;
        setRecs({ state: 'error', items: [], provider: '', note: String(e?.message || e) });
      }
    })();
    return () => { cancelled = true; };
  }, [data?.domain, data?.score]);  // refetch when scan changes

  // Derive a few status tags from the actual scan data instead of using
  // hardcoded mocks. Previously the status row showed "FILTERS PASSED /
  // SCHEMA VALID / FRESHNESS WEAK / GEMINI -2 WoW / PERPLEXITY +6 WoW"
  // regardless of what was scanned — confusing because they looked real.
  const tags = React.useMemo(() => {
    const out = [];
    const clusterById = Object.fromEntries((data.clusters || []).map(c => [c.id, c]));
    const fresh = clusterById.freshness;
    const struct = clusterById.structureReadability;
    const trust  = clusterById.trustReliability;
    if (struct && struct.score >= 0.75) out.push({ kind: 'ok', label: 'SCHEMA STRONG' });
    if (fresh && fresh.score < 0.5)     out.push({ kind: 'warn', label: 'FRESHNESS WEAK' });
    if (trust && trust.score < 0.5)     out.push({ kind: 'crit', label: 'TRUST LOW' });
    const platforms = data.platforms || [];
    if (platforms.length >= 2) {
      const best = platforms.reduce((b, p) => p.score > b.score ? p : b, platforms[0]);
      const worst = platforms.reduce((w, p) => p.score < w.score ? p : w, platforms[0]);
      if (best.score - worst.score >= 30) {
        out.push({ kind: 'info', label: `${best.name.toUpperCase()} >${(best.score - worst.score).toFixed(0)}pt > ${worst.name.toUpperCase()}` });
      }
      const cited = platforms.filter(p => p.cited).length;
      if (cited === platforms.length)      out.push({ kind: 'ok', label: 'CITED ON ALL' });
      else if (cited === 0)                out.push({ kind: 'crit', label: 'CITED ON NONE' });
      else                                  out.push({ kind: 'warn', label: `CITED ON ${cited}/${platforms.length}` });
    }
    return out.slice(0, 5);
  }, [data]);

  // One-line interpretation of the composite score. Uses the score band, not
  // just the grade letter, so the band can shift as the algorithm updates.
  const verdict = React.useMemo(() => {
    if (composite >= 80) return 'Strong. LLMs cite you confidently. Focus on freshness + cross-reference to defend.';
    if (composite >= 65) return 'Solid. The fundamentals are right; the fix list below is incremental work, not surgery.';
    if (composite >= 50) return 'Borderline. LLMs occasionally cite you. Two or three of the top fixes will move the needle visibly.';
    if (composite >= 35) return 'Weak. The page is parseable but missing the signals retrievers reward. Start at the top of the fix list.';
    return 'Critical. Hard filters or major signal gaps make the page mostly invisible. Address the top fix before anything else.';
  }, [composite]);

  return (
    <div className="view">
      {/* status bar */}
      <div style={{ padding: "10px 24px", borderBottom: "1px solid var(--line)", display: "flex", justifyContent: "space-between", fontSize: 11, color: "var(--ink-dim)" }}>
        <div style={{ display: "flex", gap: 18 }}>
          <span><span className="cap" style={{ color: "var(--ink)" }}>TARGET:</span> <span style={{ color: "var(--accent)" }}>{data.domain}</span></span>
          <span><span className="cap">BRAND:</span> {data.brand}</span>
          <span><span className="cap">SCANNED:</span> {new Date(data.scannedAt).toLocaleString()}</span>
          <span><span className="cap">DURATION:</span> {(data.scanMs/1000).toFixed(2)}s</span>
        </div>
        <div style={{ display: "flex", gap: 8, alignItems: "center" }} className="pdf-hide">
          <span className="tag ok">{(data.brand || data.domain || "REPORT").slice(0, 24).toUpperCase()}</span>
          <span className="muted">EXPORT</span>
          <button
            type="button"
            onClick={() => window.AnswenaData?.downloadPDF?.()}
            style={{
              background: "transparent", color: "var(--accent)",
              border: "1px solid var(--accent)",
              padding: "3px 10px", cursor: "pointer",
              fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 700,
              letterSpacing: ".1em", textTransform: "uppercase"
            }}
            title="Download report as PDF">[PDF]</button>
          <button
            type="button"
            onClick={() => {
              const blob = new Blob([JSON.stringify(data, null, 2)], { type: "application/json" });
              const a = document.createElement("a");
              a.href = URL.createObjectURL(blob);
              a.download = `answena-${(data.domain || "report").replace(/[^a-z0-9.-]/gi, "_")}.json`;
              a.click();
              URL.revokeObjectURL(a.href);
            }}
            style={{
              background: "transparent", color: "var(--ink-dim)",
              border: "1px solid var(--line-bright)",
              padding: "3px 10px", cursor: "pointer",
              fontFamily: "var(--font-mono)", fontSize: 10, fontWeight: 700,
              letterSpacing: ".1em", textTransform: "uppercase"
            }}
            title="Download raw report data as JSON">[JSON]</button>
        </div>
      </div>

      {/* HOW TO READ — explanatory callout above the report. Without it
          users land on a wall of numbers and ask "what am I looking at?" */}
      <section style={{ borderBottom: "1px solid var(--line)", padding: "16px 24px", background: "var(--bg-1)" }}>
        <div style={{ display: "flex", gap: 18, alignItems: "flex-start", flexWrap: "wrap" }}>
          <div style={{ flex: "1 1 380px" }}>
            <div className="lbl muted" style={{ fontSize: 10, letterSpacing: ".14em", textTransform: "uppercase", color: "var(--accent)" }}>// HOW TO READ THIS REPORT</div>
            <p style={{ margin: "6px 0 0", fontFamily: "var(--font-sans)", fontSize: 13, lineHeight: 1.6, color: "var(--ink)" }}>
              The big number is your <b>composite score (0-100)</b> — a 70/30 blend of cluster-weighted signals and live LLM probe results. Below that, six per-LLM scores show how each engine specifically would rate you (same signals, different weights). Then 10 cluster scores show <b>WHERE the score came from</b>, and the prioritised fix list shows <b>WHAT to do about it</b>. Start at the top of the fix list — it's sorted by expected lift.
            </p>
          </div>
          <div style={{ flex: "0 1 320px", borderLeft: "1px solid var(--line)", paddingLeft: 18 }}>
            <div className="lbl muted" style={{ fontSize: 10, letterSpacing: ".14em", textTransform: "uppercase" }}>// VERDICT</div>
            <p style={{ margin: "6px 0 0", fontFamily: "var(--font-sans)", fontSize: 12.5, lineHeight: 1.55, color: "var(--ink)" }}>
              {verdict}
            </p>
          </div>
        </div>
      </section>

      {/* COMPOSITE STRIP */}
      <section style={{ borderBottom: "1px solid var(--line)", display: "grid", gridTemplateColumns: "320px 1fr 280px" }}>
        <div style={{ padding: "20px 24px", borderRight: "1px solid var(--line)" }}>
          <div className="cap muted">COMPOSITE / 100</div>
          <div style={{ display: "flex", alignItems: "flex-end", gap: 14 }}>
            <span className="readout" style={{ fontSize: 96, lineHeight: 1, letterSpacing: "-.05em" }}>
              <CountUp to={composite} />
            </span>
            <div style={{ paddingBottom: 12 }}>
              <div style={{ fontSize: 28, fontWeight: 700, color: "var(--ink)" }}>{data.grade}</div>
              <div style={{ fontSize: 10, color: "var(--ink-dim)", marginTop: 4 }}><Delta v={data.delta7d} /> 7d</div>
            </div>
          </div>
          <div style={{ marginTop: 8 }}>
            <Sparkline data={data.trend30d} height={32} />
          </div>
          <div className="muted cap" style={{ marginTop: 4 }}>30-DAY TREND</div>
          <div className="muted" style={{ marginTop: 6, fontFamily: "var(--font-sans)", fontSize: 11, lineHeight: 1.45 }}>
            70% from 10 weighted signals × penalty multiplier · 30% from live LLM citation probes. Higher = more likely to be cited in answer text.
          </div>
        </div>

        <div style={{ padding: "18px 24px", borderRight: "1px solid var(--line)" }}>
          <div className="cap muted">EXECUTIVE SUMMARY</div>
          <p style={{ margin: "8px 0 0", fontFamily: "var(--font-sans)", fontSize: 14, lineHeight: 1.6, color: "var(--ink)" }}>
            {data.summary}
          </p>
          <div style={{ marginTop: 14, display: "flex", gap: 8, flexWrap: "wrap" }}>
            {tags.length === 0
              ? <span className="muted" style={{ fontSize: 11 }}>No standout signals — see clusters below.</span>
              : tags.map((t, i) => <span key={i} className={`tag ${t.kind}`}>{t.label}</span>)}
          </div>
        </div>

        <div style={{ padding: "20px 24px" }}>
          <div className="cap muted">PER-LLM AT A GLANCE</div>
          {data.platforms.map((p) => (
            <div key={p.id} style={{ display: "grid", gridTemplateColumns: "78px 1fr 32px", gap: 8, alignItems: "center", padding: "5px 0" }}>
              <span style={{ color: "var(--ink)", fontSize: 11 }}>{p.name}</span>
              <Meter value={p.score / 100} />
              <span className="tabular" style={{ textAlign: "right", color: "var(--accent)", fontWeight: 700, fontSize: 12 }}>{p.score}</span>
            </div>
          ))}
        </div>
      </section>

      {/* PER-LLM HERO — six vertical readouts */}
      <section>
        <div className="section-h">
          <div>
            <div className="lbl">// PER-LLM PLATFORM SCORES</div>
            <h2>How each engine sees you.</h2>
            <p className="muted" style={{ margin: "4px 0 0", fontFamily: "var(--font-sans)", fontSize: 12, lineHeight: 1.5, maxWidth: 720 }}>
              Same 10 signals, re-weighted to each engine's documented citation bias. The big number is HEURISTIC (always available — derived from your cluster scores); MENTION / CITATION rates come from LIVE API probes (require the matching API key). "CITED" = the engine cited or mentioned you in at least one probe; if you don't have its API key, a positive heuristic score still earns the badge.
            </p>
          </div>
          <div className="muted">{data.platforms.length} platforms · heuristic + live blend</div>
        </div>
        <div className="llm-grid">
          {data.platforms.map((p) => (
            <div key={p.id} className={`llm-col ${p.cited ? "" : "dim"}`}>
              <span className={`citemark ${p.cited ? "tag ok" : "tag crit"}`}>
                {p.cited ? "CITED" : "NOT CITED"}
              </span>
              <div className="h">
                <div>
                  <div className="n">{p.name}</div>
                  <div className="p">{p.provider}</div>
                </div>
              </div>
              <div className="score-big tabular">
                <CountUp to={p.score} />
              </div>
              <div className="cap muted" style={{ marginTop: -6 }}>
                <Delta v={p.delta7d} /> · 7D
              </div>

              <div className="stat-row">
                <div><div className="k">MENTION</div><div className="tabular" style={{ fontSize: 14, color: "var(--ink)", fontWeight: 700 }}>{(p.mentionRate * 100).toFixed(0)}%</div></div>
                <div><div className="k">CITATION</div><div className="tabular" style={{ fontSize: 14, color: "var(--ink)", fontWeight: 700 }}>{(p.citationRate * 100).toFixed(0)}%</div></div>
                <div><div className="k">AVG POS</div><div className="tabular" style={{ fontSize: 14, color: "var(--ink)", fontWeight: 700 }}>{p.avgPosition.toFixed(1)}</div></div>
                <div><div className="k">PROBES</div><div className="tabular" style={{ fontSize: 14, color: "var(--ink)", fontWeight: 700 }}>{p.probesCited}/{p.probesRun}</div></div>
              </div>

              <div className="probe">
                <div className="cap muted" style={{ marginBottom: 4 }}>SAMPLE QUERY</div>
                <div style={{ color: "var(--ink)" }}>{p.sampleQuery}</div>
                <q>{p.sampleAnswer}</q>
              </div>
            </div>
          ))}
        </div>
      </section>

      {/* RECOMMENDATIONS — Claude-written, paste-able. Sits right after the
          per-LLM hero so users see ACTIONABLE prose before the deep cluster
          tables. Falls back to the heuristic fix list if Claude is offline. */}
      <section style={{ borderTop: "1px solid var(--line)", background: "linear-gradient(180deg, rgba(92,255,157,0.04), transparent)" }}>
        <div className="section-h">
          <div>
            <div className="lbl">// RECOMMENDATIONS · WHAT TO DO</div>
            <h2>Concrete fixes, written for you.</h2>
            <p className="muted" style={{ margin: "4px 0 0", fontFamily: "var(--font-sans)", fontSize: 12, lineHeight: 1.5, maxWidth: 720 }}>
              Each card is a paste-able rewrite — actual copy, schema, or HTML you can drop onto your page. <b>Generated by Claude</b> from your top 6 fixes + cluster scores. Start at the top; each one is ranked by expected lift.
            </p>
          </div>
          <div className="muted" style={{ fontSize: 10 }}>
            {recs.state === 'ready' && recs.provider}
            {recs.state === 'loading' && 'Generating…'}
            {recs.state === 'error' && 'Recommendations offline'}
          </div>
        </div>

        <div style={{ padding: "0 24px 24px" }}>
          {recs.state === 'idle' && (
            <div className="muted" style={{ padding: "20px 0", fontSize: 12, fontFamily: "var(--font-mono)" }}>
              Run a scan to get tailored recommendations.
            </div>
          )}

          {recs.state === 'loading' && (
            <div className="muted" style={{ padding: "30px 0", textAlign: "center", fontSize: 12, fontFamily: "var(--font-mono)", letterSpacing: ".08em" }}>
              ▣ Claude is writing concrete fixes for {data.domain}…
              <div style={{ fontSize: 10.5, marginTop: 6 }}>typically 6-12s</div>
            </div>
          )}

          {recs.state === 'error' && (
            <div className="muted" style={{ padding: "16px 18px", border: "1px solid var(--warn)", borderLeft: "3px solid var(--warn)", color: "var(--warn)", fontSize: 12, fontFamily: "var(--font-mono)" }}>
              Couldn't reach the recommendations service: {recs.note}
              <br/>
              <span className="muted" style={{ color: "var(--ink-dim)" }}>Falling back to the heuristic fix list below — same ranked order, just less prose.</span>
            </div>
          )}

          {recs.state === 'ready' && recs.items.length === 0 && (
            <div className="muted" style={{ padding: "20px 0", fontSize: 12, fontFamily: "var(--font-mono)" }}>
              No recommendations generated. {recs.note}
            </div>
          )}

          {recs.state === 'ready' && recs.items.length > 0 && (
            <>
              {recs.note && (
                <div className="muted" style={{ marginBottom: 12, fontSize: 11, fontFamily: "var(--font-mono)", letterSpacing: ".04em" }}>
                  ⓘ {recs.note}
                </div>
              )}
              <div style={{ display: "grid", gap: 12 }}>
                {recs.items.map((rec, i) => {
                  const tagColor = {
                    rewrite: 'var(--info)',
                    add: 'var(--accent)',
                    restructure: 'var(--warn)',
                    remove: 'var(--crit)'
                  }[rec.tag] || 'var(--ink-dim)';
                  return (
                    <div key={i} style={{ border: "1px solid var(--line-bright)", borderLeft: `3px solid ${tagColor}`, background: "var(--bg-1)", padding: "14px 18px" }}>
                      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "baseline", marginBottom: 6 }}>
                        <div style={{ display: "flex", gap: 10, alignItems: "baseline" }}>
                          <span className="muted tabular" style={{ fontSize: 10, letterSpacing: ".12em" }}>REC/{String(i + 1).padStart(2, "0")}</span>
                          {rec.tag && (
                            <span style={{ fontSize: 10, fontFamily: "var(--font-mono)", color: tagColor, border: `1px solid ${tagColor}`, padding: "1px 7px", textTransform: "uppercase", letterSpacing: ".1em" }}>
                              {rec.tag}
                            </span>
                          )}
                          {rec.component && (
                            <span className="muted" style={{ fontSize: 10, fontFamily: "var(--font-mono)" }}>· {rec.component}</span>
                          )}
                        </div>
                      </div>
                      <h4 style={{ margin: "0 0 8px", fontFamily: "var(--font-mono)", fontSize: 14, fontWeight: 700, color: "var(--ink)" }}>
                        {rec.title}
                      </h4>
                      {rec.rewrite && (
                        <pre style={{ margin: "0 0 8px", padding: "10px 12px", background: "var(--bg)", border: "1px solid var(--line)", fontFamily: "var(--font-mono)", fontSize: 12, lineHeight: 1.5, color: "var(--ink)", whiteSpace: "pre-wrap", overflow: "auto", maxHeight: 280 }}>
                          {rec.rewrite}
                        </pre>
                      )}
                      {rec.why && (
                        <div className="muted" style={{ fontFamily: "var(--font-sans)", fontSize: 12, lineHeight: 1.5 }}>
                          <b style={{ color: "var(--ink-dim)", fontFamily: "var(--font-mono)", fontSize: 10, letterSpacing: ".1em", textTransform: "uppercase" }}>Why:</b> {rec.why}
                        </div>
                      )}
                    </div>
                  );
                })}
              </div>
            </>
          )}
        </div>
      </section>

      {/* CLUSTERS — detail */}
      <section style={{ borderTop: "1px solid var(--line)" }}>
        <div className="section-h">
          <div>
            <div className="lbl">// 10 CLUSTER SCORES</div>
            <h2>Signal-by-signal breakdown.</h2>
            <p className="muted" style={{ margin: "4px 0 0", fontFamily: "var(--font-sans)", fontSize: 12, lineHeight: 1.5, maxWidth: 720 }}>
              Each cluster scores a different aspect of "would an LLM cite this?". WEIGHT = how much the cluster contributes to the composite. SCORE = how well your page does on it (0-100). CONTRIB = weight × score = points contributed to the composite. <b>Lowest scores with the highest weights are where to focus</b> — the fix list below ranks them automatically.
            </p>
          </div>
          <div className="muted">composite = Σ ( weight<sub>i</sub> × score<sub>i</sub> )</div>
        </div>
        <div style={{ padding: "0 24px 12px" }}>
          <div className="row" style={{ gridTemplateColumns: "30px 1fr 70px 60px 1fr 70px", color: "var(--ink-mute)", fontSize: 10, letterSpacing: ".12em", textTransform: "uppercase", borderBottom: "1px solid var(--line-bright)" }}>
            <span>#</span><span>CLUSTER</span><span style={{ textAlign: "right" }}>WEIGHT</span><span style={{ textAlign: "right" }}>SCORE</span><span>BAR</span><span style={{ textAlign: "right" }}>CONTRIB</span>
          </div>
          {data.clusters.map((c, i) => {
            const contrib = c.weight * c.score * 100;
            const desc = CLUSTER_DESC[c.id];
            return (
              <div key={c.id} style={{ borderBottom: "1px solid var(--line)" }}>
                <div className="row" style={{ gridTemplateColumns: "30px 1fr 70px 60px 1fr 70px", borderBottom: 0 }}>
                  <span className="muted tabular">{String(i + 1).padStart(2, "0")}</span>
                  <span style={{ color: "var(--ink)", fontWeight: 600 }}>{c.label}</span>
                  <span className="muted tabular" style={{ textAlign: "right" }}>×{c.weight.toFixed(2)}</span>
                  <span className="tabular" style={{ textAlign: "right", color: c.score < 0.5 ? "var(--crit)" : c.score < 0.7 ? "var(--warn)" : "var(--accent)", fontWeight: 700 }}>
                    {(c.score * 100).toFixed(0)}
                  </span>
                  <Meter value={c.score} />
                  <span className="tabular" style={{ textAlign: "right", color: "var(--ink)" }}>+{contrib.toFixed(1)}</span>
                </div>
                {desc && (
                  <div style={{ padding: "0 14px 8px 44px", fontFamily: "var(--font-sans)", fontSize: 11, color: "var(--ink-dim)", lineHeight: 1.45 }}>
                    {desc}
                  </div>
                )}
              </div>
            );
          })}
        </div>
      </section>

      {/* SPIDERS */}
      <section style={{ borderTop: "1px solid var(--line)" }}>
        <div className="section-h">
          <div>
            <div className="lbl">// 8 SPIDER PERSONAS</div>
            <h2>Each crawls with a different objective.</h2>
            <p className="muted" style={{ margin: "4px 0 0", fontFamily: "var(--font-sans)", fontSize: 12, lineHeight: 1.5, maxWidth: 720 }}>
              Each spider re-scores the same page through one specific lens. <b>Disagreement between spiders is the signal</b>: if RETRIEVAL and CITATION are high but ENTITY is low, your page is technically retrievable but the LLM doesn't know which brand it's about. The narrowest spider score tells you the layer to fix first. The Agents view shows them running live.
            </p>
          </div>
          <div className="muted">retrieval · citation · intent · entity · trust · freshness · actionability · multimodal</div>
        </div>
        <div className="spiders">
          {data.spiders.map((s) => {
            const pct = (s.score * 100).toFixed(0);
            return (
              <div key={s.id} className="spider">
                <div className="lab">
                  <span className="name">{s.label}</span>
                  <span className="pct tabular" style={{ color: s.score < 0.5 ? "var(--crit)" : s.score < 0.7 ? "var(--warn)" : "var(--accent)" }}>{pct}</span>
                </div>
                <Meter value={s.score} />
                <div className="focus">FOCUS · {s.focus}</div>
              </div>
            );
          })}
        </div>
      </section>

      {/* FIXES — heuristic backup view, complementary to RECOMMENDATIONS above */}
      <section style={{ borderTop: "1px solid var(--line)" }}>
        <div className="section-h">
          <div>
            <div className="lbl">// FIX LIST · technical breakdown</div>
            <h2>Same fixes, ranked numerically.</h2>
            <p className="muted" style={{ margin: "4px 0 0", fontFamily: "var(--font-sans)", fontSize: 12, lineHeight: 1.5, maxWidth: 720 }}>
              The terse heuristic version of the recommendations above — useful when you want to see the raw expected-lift math or filter by cluster. EXPECTED LIFT = weight × (1 − score) is the max points you'd gain. EFFORT (XS / S / M / L) is a rough engineering estimate.
            </p>
          </div>
          <div className="muted">lift = weight × (1 − score) · top {data.fixes?.length || 0}</div>
        </div>
        {data.fixes.map((f, i) => (
          <div key={i} className="fix">
            <div>
              <div className="impact tabular">{f.lift}</div>
              <small>EXPECTED LIFT</small>
            </div>
            <div>
              <div style={{ display: "flex", gap: 10, alignItems: "center", marginBottom: 4 }}>
                <span className="muted tabular">FIX/{String(i+1).padStart(2,"0")}</span>
                <span className="tag info">{f.cluster}</span>
              </div>
              <h4>{f.title}</h4>
              <p>{f.detail}</p>
            </div>
            <div className="effort">
              <div className="cap muted">EFFORT</div>
              <div style={{ fontSize: 16, fontWeight: 700, color: "var(--ink)", marginTop: 2 }}>{f.effort}</div>
            </div>
            <div className="num">↗</div>
          </div>
        ))}
      </section>

      {/* RAW PROBES */}
      <section style={{ borderTop: "1px solid var(--line)" }}>
        <div className="section-h">
          <div>
            <div className="lbl">// RAW PROBE LOG</div>
            <h2>Every query, every model, every response.</h2>
            <p className="muted" style={{ margin: "4px 0 0", fontFamily: "var(--font-sans)", fontSize: 12, lineHeight: 1.5, maxWidth: 720 }}>
              The actual buyer-intent queries we ran against each LLM, with the verbatim responses. <b>"UNDER-INDEXED" doesn't mean the score is wrong</b> — it means the LLM's answer for that query didn't mention or cite the brand. Click each row to see the sample query + response. Useful for "why does Gemini not cite us for X?" debugging.
            </p>
          </div>
          <div className="muted">{data.platforms.length} models</div>
        </div>
        <div style={{ padding: "0 24px 24px" }}>
          {data.platforms.map((p) => (
            <details key={p.id} style={{ borderBottom: "1px solid var(--line)", padding: "12px 0" }}>
              <summary style={{ display: "grid", gridTemplateColumns: "120px 1fr 100px 100px 100px", gap: 16, alignItems: "center" }}>
                <span style={{ color: "var(--ink)", fontWeight: 700 }}>{p.name}</span>
                <span className="muted">probes returned <span style={{ color: "var(--ink)" }}>{p.probesCited}/{p.probesRun}</span> with brand mention</span>
                <span className="tabular muted">mention {(p.mentionRate*100).toFixed(0)}%</span>
                <span className="tabular muted">cite {(p.citationRate*100).toFixed(0)}%</span>
                <span className={p.cited ? "up" : "down"}>{p.cited ? "● PASS" : "● UNDER-INDEXED"}</span>
              </summary>
              <div style={{ marginTop: 8, padding: "12px 16px", background: "var(--bg)", border: "1px solid var(--line)" }}>
                <div className="cap muted">PROBE 1/8 · {p.sampleQuery}</div>
                <div style={{ fontFamily: "var(--font-sans)", fontSize: 12.5, color: "var(--ink-dim)", marginTop: 8, lineHeight: 1.6 }}>
                  → {p.sampleAnswer}
                </div>
              </div>
            </details>
          ))}
        </div>
      </section>
    </div>
  );
}

window.Report = Report;
