/* NutriDMS enterprise analytics workspace.
   Loaded after screens/extra.jsx so this live-data implementation replaces
   the legacy demonstration AnalyticsScreen without changing other routes. */

const AN_REVIEW_STATUSES = ["pending-review", "compliance-review", "changes-requested", "review", "validating"];
const AN_RELEASED_STATUSES = ["approved", "published"];

function anConnected() {
  try { return !!(window.NutriData && window.NutriData.isConnected && window.NutriData.isConnected()); } catch (_) { return false; }
}
function anTenantRows(rows) {
  const list = Array.isArray(rows) ? rows.filter(Boolean) : [];
  return anConnected() ? list.filter((row) => row.__remote) : list;
}
function anRecordDate(row) {
  const raw = row.updated || row.submitted || row.created_at || row.updated_at || "";
  const parsed = raw ? new Date(raw) : null;
  return parsed && !Number.isNaN(parsed.getTime()) ? parsed : null;
}
function anRangeDays(range) {
  if (range === "7d") return 7;
  if (range === "90d") return 90;
  if (range === "ytd") {
    const now = new Date();
    return Math.max(1, Math.ceil((now - new Date(now.getFullYear(), 0, 1)) / 86400000));
  }
  return 30;
}
function anWithin(row, range) {
  const date = anRecordDate(row);
  if (!date) return true;
  return Date.now() - date.getTime() <= anRangeDays(range) * 86400000;
}
function anMembers() {
  try {
    const saved = JSON.parse(localStorage.getItem("nutridms_members_v1") || "[]");
    if (Array.isArray(saved) && saved.length) return saved;
  } catch (_) {}
  const auth = window.__nutridmsAuthenticatedUser;
  if (auth) return [{ ...auth, name: auth.name || "Current member", status: "active", role: auth.role || "member", lastActive: "Now" }];
  try { return Array.isArray(window.USERS) ? window.USERS : []; } catch (_) { return []; }
}
function anAuditRows(rows) { return Array.isArray(rows) ? rows : []; }
function anComplianceData() {
  try { return window.compLoad ? window.compLoad() : { rules: [], allergens: [], healthtags: [], conditions: [] }; }
  catch (_) { return { rules: [], allergens: [], healthtags: [], conditions: [] }; }
}
function anFlags(row) {
  try {
    if (!window.complianceCheck) return [];
    const item = row.__kind === "recipe" && window.compRecipeItem
      ? window.compRecipeItem(row)
      : { name: row.name, nutr: row.nutr || {}, ingredients: [{ name: row.name }], allergens: row.allergens || [] };
    return window.complianceCheck(item, row.__kind) || [];
  } catch (_) { return []; }
}
function anSeries(rows, days, predicate) {
  const buckets = Math.min(14, Math.max(7, days));
  const out = Array(buckets).fill(0);
  rows.forEach((row) => {
    if (predicate && !predicate(row)) return;
    const date = anRecordDate(row);
    if (!date) return;
    const age = Math.floor((Date.now() - date.getTime()) / 86400000);
    if (age < 0 || age >= days) return;
    const index = Math.min(buckets - 1, buckets - 1 - Math.floor((age / days) * buckets));
    out[index] += 1;
  });
  return out;
}
function anFormat(value) { return value == null || Number.isNaN(value) ? "—" : new Intl.NumberFormat().format(value); }
function anMoney(value) { return value == null || Number.isNaN(value) ? "—" : new Intl.NumberFormat(undefined, { style: "currency", currency: "USD", maximumFractionDigits: 0 }).format(value); }
function anCsvCell(value) { const s = String(value == null ? "" : value); return /[\",\n]/.test(s) ? '"' + s.replace(/"/g, '""') + '"' : s; }
function anDownload(filename, mime, content) {
  const blob = new Blob([content], { type: mime });
  const url = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = url; link.download = filename; document.body.appendChild(link); link.click(); link.remove();
  setTimeout(() => URL.revokeObjectURL(url), 500);
}

function AnLineChart({ series }) {
  const width = 720, height = 250, pad = 32;
  const values = series.flatMap((item) => item.values);
  const max = Math.max(1, ...values);
  const count = Math.max(2, ...series.map((item) => item.values.length));
  const x = (i) => pad + (i / (count - 1)) * (width - pad * 2);
  const y = (v) => height - pad - (v / max) * (height - pad * 2);
  const path = (values) => values.map((v, i) => `${i ? "L" : "M"}${x(i)},${y(v)}`).join(" ");
  return (
    <svg className="ea-line-chart" viewBox={`0 0 ${width} ${height}`} role="img" aria-label="Throughput trend">
      {[0, .25, .5, .75, 1].map((n) => <g key={n}><line x1={pad} x2={width-pad} y1={pad+n*(height-pad*2)} y2={pad+n*(height-pad*2)} /><text x={pad-8} y={pad+n*(height-pad*2)+4}>{Math.round(max*(1-n))}</text></g>)}
      {series.map((item) => <path key={item.label} d={path(item.values)} fill="none" stroke={item.color} strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />)}
      {series.map((item) => item.values.map((v, i) => i === item.values.length - 1 ? <circle key={item.label+i} cx={x(i)} cy={y(v)} r="5" fill="#fff" stroke={item.color} strokeWidth="3" /> : null))}
    </svg>
  );
}

function AnMetric({ icon, label, value, note, tone = "green" }) {
  return <div className={`ea-metric ${tone}`}><div className="ea-metric-top"><span className="ea-icon"><Icon name={icon} size={17} /></span><span className="ea-live-dot">Live</span></div><strong>{value}</strong><span>{label}</span><small>{note}</small></div>;
}

function AnCard({ title, sub, action, className = "", children }) {
  return <section className={`ea-card ${className}`}><header><div><h3>{title}</h3>{sub && <p>{sub}</p>}</div>{action}</header>{children}</section>;
}

function AnalyticsScreen() {
  const { toast, setPage } = useApp();
  const [range, setRange] = React.useState("30d");
  const [contentType, setContentType] = React.useState("all");
  const [status, setStatus] = React.useState("all");
  const [savedView, setSavedView] = React.useState("Executive operations");
  const [, refresh] = React.useState(0);
  const [auditRows, setAuditRows] = React.useState([]);
  const [roi, setRoi] = React.useState(() => {
    try { return { minutes: 0, hourly: 0, platform: 0, risk: 0, ...JSON.parse(localStorage.getItem("nutridms_analytics_roi") || "{}") }; }
    catch (_) { return { minutes: 0, hourly: 0, platform: 0, risk: 0 }; }
  });
  const [exportLog, setExportLog] = React.useState(() => {
    try { return JSON.parse(localStorage.getItem("nutridms_analytics_exports") || "[]"); } catch (_) { return []; }
  });
  React.useEffect(() => {
    const bump = () => refresh((n) => n + 1);
    const events = ["nutridms-recipes", "nutridms-ingredients", "nutridms-audit", "nutridms-members-changed", "nutridms-compliance", "nutridms-mealprograms", "nutridms-inventory", "nutridms-assignments", "nutridms-cep", "nutridms-rmenus", "nutridms-offerings", "nutridms-backend"];
    events.forEach((name) => window.addEventListener(name, bump));
    return () => events.forEach((name) => window.removeEventListener(name, bump));
  }, []);
  React.useEffect(() => {
    let active = true;
    const api = window.NutriData && window.NutriData.audit;
    if (!api || typeof api.list !== "function" || (window.NutriData.isConnected && !window.NutriData.isConnected())) return () => { active = false; };
    api.list({ limit: 200 })
      .then((page) => {
        if (!active) return;
        const rows = (page && page.results) || [];
        setAuditRows(rows.map((row) => ({
          when: row.created_at,
          who: (row.actor && row.actor.label) || "System",
          action: row.action,
          target: (row.entity && row.entity.label) || row.event_summary || "Workspace event",
          severity: row.presentation && row.presentation.severity,
          ip: row.ip,
        })));
      })
      .catch(() => { if (active) setAuditRows([]); });
    return () => { active = false; };
  }, []);

  const recipes = anTenantRows(window.RECIPES || []).map((row) => ({ ...row, __kind: "recipe" }));
  const ingredients = anTenantRows(window.INGREDIENT_ITEMS || []).map((row) => ({ ...row, __kind: "ingredient" }));
  const allRecords = [...recipes, ...ingredients];
  const periodRecords = allRecords.filter((row) => anWithin(row, range));
  const filtered = periodRecords.filter((row) => (contentType === "all" || row.__kind === contentType) && (status === "all" || row.status === status));
  const submitted = filtered.filter((row) => row.status !== "draft");
  const released = filtered.filter((row) => AN_RELEASED_STATUSES.includes(row.status));
  const inReview = filtered.filter((row) => AN_REVIEW_STATUSES.includes(row.status));
  const rejected = filtered.filter((row) => row.status === "rejected");
  const members = anMembers();
  const activeMembers = members.filter((member) => member.status !== "inactive");
  const audit = anAuditRows(auditRows).filter((row) => anWithin(row, range));
  const compliance = anComplianceData();
  const activeRules = [...(compliance.rules || []), ...(compliance.allergens || []), ...(compliance.healthtags || [])].filter((row) => row.status === "active");
  const evaluated = activeRules.length ? filtered.map((row) => ({ row, flags: anFlags(row) })) : [];
  const blockers = evaluated.flatMap((item) => item.flags).filter((flag) => /critical|severe/i.test(flag.severity || ""));
  const warnings = evaluated.flatMap((item) => item.flags).filter((flag) => !/critical|severe/i.test(flag.severity || ""));
  const passed = evaluated.filter((item) => item.flags.length === 0).length;
  const complianceScore = evaluated.length ? Math.round((passed / evaluated.length) * 100) : null;
  const cycles = released.map((row) => {
    const start = row.submitted ? new Date(row.submitted) : null;
    const end = row.updated ? new Date(row.updated) : null;
    return start && end && !Number.isNaN(start.getTime()) && !Number.isNaN(end.getTime()) ? Math.max(0, (end - start) / 86400000) : null;
  }).filter((value) => value != null);
  const avgCycle = cycles.length ? cycles.reduce((a, b) => a + b, 0) / cycles.length : null;
  const publishRate = submitted.length ? Math.round((released.length / submitted.length) * 100) : null;
  const days = anRangeDays(range);
  const submissionsSeries = anSeries(filtered, days, (row) => row.status !== "draft");
  const releasesSeries = anSeries(filtered, days, (row) => AN_RELEASED_STATUSES.includes(row.status));
  const statusGroups = [
    ["Draft", filtered.filter((row) => row.status === "draft").length, "#98A2B3"],
    ["In review", inReview.length, "#F79009"],
    ["Released", released.length, "#16803A"],
    ["Rejected", rejected.length, "#F04438"],
  ];
  const totalForDonut = Math.max(1, statusGroups.reduce((sum, item) => sum + item[1], 0));
  let angle = 0;
  const donutStops = statusGroups.map((item) => { const start = angle; angle += item[1] / totalForDonut * 360; return `${item[2]} ${start}deg ${angle}deg`; }).join(", ");

  const applySavedView = (view) => {
    setSavedView(view);
    if (view === "Compliance readiness") { setContentType("all"); setStatus("all"); setTimeout(() => document.querySelector(".ea-grid-three")?.scrollIntoView({ behavior: "smooth", block: "start" }), 0); }
    else if (view === "Publishing velocity") { setContentType("all"); setStatus("all"); setTimeout(() => document.querySelector(".ea-grid-main")?.scrollIntoView({ behavior: "smooth", block: "start" }), 0); }
    else if (view === "ROI detail") setTimeout(() => document.querySelector(".ea-grid-roi")?.scrollIntoView({ behavior: "smooth", block: "start" }), 0);
    else if (view === "Full platform operations") setTimeout(() => window.AnalyticsOpsScroll && window.AnalyticsOpsScroll("ea-content"), 0);
    else window.scrollTo({ top: 0, behavior: "smooth" });
  };

  const setRoiValue = (key, value) => {
    const next = { ...roi, [key]: Math.max(0, Number(value) || 0) };
    setRoi(next); try { localStorage.setItem("nutridms_analytics_roi", JSON.stringify(next)); } catch (_) {}
  };
  const hoursSaved = released.length * roi.minutes / 60;
  const laborBenefit = hoursSaved * roi.hourly;
  const riskScenario = blockers.length * roi.risk;
  const grossBenefit = laborBenefit + riskScenario;
  const netBenefit = grossBenefit - roi.platform;
  const roiPercent = roi.platform > 0 ? (netBenefit / roi.platform) * 100 : null;
  const paybackDays = grossBenefit > 0 && roi.platform > 0 ? roi.platform / grossBenefit * days : null;

  const logExport = (type, rows) => {
    const next = [{ type, rows, when: new Date().toLocaleString() }, ...exportLog].slice(0, 8);
    setExportLog(next); try { localStorage.setItem("nutridms_analytics_exports", JSON.stringify(next)); } catch (_) {}
  };
  const exportData = (type) => {
    const stamp = new Date().toISOString().slice(0, 10);
    if (type === "records") {
      const header = ["type", "name", "status", "owner", "submitted", "updated"];
      const rows = filtered.map((row) => [row.__kind, row.name, row.status, row.contributor && row.contributor.name, row.submitted, row.updated]);
      anDownload(`nutridms-records-${stamp}.csv`, "text/csv", [header, ...rows].map((r) => r.map(anCsvCell).join(",")).join("\n"));
      logExport("Records CSV", rows.length);
    } else if (type === "audit") {
      const header = ["timestamp", "actor", "action", "target", "severity", "ip"];
      const rows = audit.map((row) => [row.when, row.who, row.action, row.target, row.severity, row.ip]);
      anDownload(`nutridms-audit-${stamp}.csv`, "text/csv", [header, ...rows].map((r) => r.map(anCsvCell).join(",")).join("\n"));
      logExport("Audit CSV", rows.length);
    } else if (type === "json") {
      const payload = { generatedAt: new Date().toISOString(), filters: { range, contentType, status }, metrics: { records: filtered.length, submitted: submitted.length, released: released.length, inReview: inReview.length, complianceScore }, roi: { assumptions: roi, hoursSaved, laborBenefit, riskScenario, grossBenefit, netBenefit, roiPercent, paybackDays }, records: filtered, audit };
      anDownload(`nutridms-analytics-${stamp}.json`, "application/json", JSON.stringify(payload, null, 2));
      logExport("Analytics JSON", filtered.length + audit.length);
    } else {
      window.print(); logExport("Print / PDF", filtered.length);
    }
    toast("Analytics export prepared");
  };

  const queue = filtered.filter((row) => AN_REVIEW_STATUSES.includes(row.status)).slice(0, 7);
  const quality = [
    ["Nutrition populated", filtered.filter((row) => row.__kind === "recipe" ? row.calories != null : row.nutr && row.nutr.calories != null).length],
    ["Owner assigned", filtered.filter((row) => row.reviewer || row.contributor).length],
    ["Images attached", filtered.filter((row) => row.cover || row.image || row.image_url).length],
    ["Compliance evaluated", evaluated.length],
  ];

  return (
    <div className="enterprise-analytics">
      <Crumbs path={[{ label: "Analytics" }]} />
      <div className="ea-hero">
        <div><span className="ea-eyebrow"><Icon name="line-chart" size={14} /> Live intelligence workspace</span><h1>Analytics &amp; ROI</h1><p>Operational reporting across content, review, compliance, people, audit activity, and value realization.</p></div>
        <div className="ea-hero-actions"><button className="btn secondary" onClick={() => setPage("audit")}><Icon name="history" size={16} /> Open audit log</button><button className="btn primary" onClick={() => document.getElementById("ea-exports")?.scrollIntoView({ behavior: "smooth" })}><Icon name="download" size={16} /> Export center</button></div>
      </div>

      <div className="ea-commandbar">
        <label><span>Saved view</span><select value={savedView} onChange={(e) => applySavedView(e.target.value)}><option>Executive operations</option><option>Full platform operations</option><option>Compliance readiness</option><option>Publishing velocity</option><option>ROI detail</option></select></label>
        <label><span>Period</span><select value={range} onChange={(e) => setRange(e.target.value)}><option value="7d">Last 7 days</option><option value="30d">Last 30 days</option><option value="90d">Last 90 days</option><option value="ytd">Year to date</option></select></label>
        <label><span>Content</span><select value={contentType} onChange={(e) => setContentType(e.target.value)}><option value="all">Recipes + ingredients</option><option value="recipe">Recipes</option><option value="ingredient">Ingredients</option></select></label>
        <label><span>Status</span><select value={status} onChange={(e) => setStatus(e.target.value)}><option value="all">All statuses</option><option value="draft">Draft</option><option value="pending-review">Pending review</option><option value="approved">Approved</option><option value="published">Published</option><option value="rejected">Rejected</option></select></label>
        <button className="ea-refresh" onClick={() => refresh((n) => n + 1)}><Icon name="refresh-cw" size={15} /> Refresh</button>
      </div>

      <div className="ea-trustbar"><span><i className={anConnected() ? "on" : ""} /> {anConnected() ? "Tenant API connected" : "Local workspace mode"}</span><span>{filtered.length} records in view</span><span>{activeRules.length ? `${activeRules.length} active compliance rules` : "Compliance not configured"}</span><span>Updated {new Date().toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}</span></div>

      {window.AnalyticsOperationsNav && <window.AnalyticsOperationsNav setPage={setPage} />}

      <div className="ea-metrics">
        <AnMetric icon="database" label="Records in scope" value={anFormat(filtered.length)} note={`${recipes.length} recipes · ${ingredients.length} ingredients`} />
        <AnMetric icon="upload-cloud" label="Submitted" value={anFormat(submitted.length)} note={`${range.toUpperCase()} activity window`} tone="blue" />
        <AnMetric icon="badge-check" label="Released to library" value={anFormat(released.length)} note={publishRate == null ? "No submissions to compare" : `${publishRate}% of submitted`} tone="violet" />
        <AnMetric icon="clipboard-check" label="In review" value={anFormat(inReview.length)} note={`${rejected.length} rejected`} tone="amber" />
        <AnMetric icon="timer" label="Avg. create → release" value={avgCycle == null ? "—" : `${avgCycle.toFixed(1)}d`} note={cycles.length ? `${cycles.length} released records measured` : "Waiting for timestamped releases"} tone="cyan" />
        <AnMetric icon="shield-check" label="Compliance" value={complianceScore == null ? "—" : `${complianceScore}%`} note={activeRules.length ? `${blockers.length} blocking · ${warnings.length} warnings` : "No active rule set"} tone="green" />
        <AnMetric icon="users" label="Active members" value={anFormat(activeMembers.length)} note={`${members.length} total workspace members`} tone="pink" />
        <AnMetric icon="scroll-text" label="Audited actions" value={anFormat(audit.length)} note={`${range.toUpperCase()} append-only events`} tone="slate" />
      </div>

      <div className="ea-grid ea-grid-main">
        <AnCard title="Throughput & release velocity" sub={`Tenant records over ${days} days`} action={<div className="ea-legend"><span><i className="sub" />Submitted</span><span><i className="pub" />Released</span></div>}><AnLineChart series={[{ label: "Submitted", values: submissionsSeries, color: "#16803A" }, { label: "Released", values: releasesSeries, color: "#635BFF" }]} /><div className="ea-chart-foot"><span>Start</span><strong>{submissionsSeries.reduce((a,b)=>a+b,0)} submitted · {releasesSeries.reduce((a,b)=>a+b,0)} released</strong><span>Today</span></div></AnCard>
        <AnCard title="Publishing funnel" sub="Current records by workflow stage" className="ea-funnel-card"><div className="ea-funnel">{[["Created", filtered.length], ["Submitted", submitted.length], ["In review", inReview.length], ["Released", released.length]].map(([label, value], index) => <div key={label}><span>{index + 1}</span><div><b>{label}</b><small>{filtered.length ? Math.round(value / filtered.length * 100) : 0}% of records</small></div><strong>{value}</strong><i style={{ width: `${filtered.length ? Math.max(4, value / filtered.length * 100) : 0}%` }} /></div>)}</div></AnCard>
      </div>

      <div className="ea-grid ea-grid-three">
        <AnCard title="Pipeline mix" sub="Recipes and ingredients by status"><div className="ea-donut-wrap"><div className="ea-donut" style={{ background: `conic-gradient(${donutStops || "#EAECF0 0deg 360deg"})` }}><span><strong>{filtered.length}</strong>records</span></div><div className="ea-donut-legend">{statusGroups.map(([label, value, color]) => <div key={label}><i style={{ background: color }} /><span>{label}</span><strong>{value}</strong></div>)}</div></div></AnCard>
        <AnCard title="Compliance outcomes" sub={activeRules.length ? "Rule-based evaluation across records" : "Configure FDA/CFIA rules to activate scoring"}><div className="ea-outcomes">{[["Passed", passed, "ok"], ["Warnings", warnings.length, "warn"], ["Blocking", blockers.length, "bad"], ["Not evaluated", activeRules.length ? Math.max(0, filtered.length-evaluated.length) : filtered.length, "muted"]].map(([label,value,tone]) => <div key={label}><span><i className={tone} />{label}</span><strong>{value}</strong></div>)}</div><button className="ea-link" onClick={() => setPage("compliance-dashboard")}>Open compliance center <Icon name="arrow-up-right" size={14} /></button></AnCard>
        <AnCard title="Data quality coverage" sub="Publish-critical field readiness"><div className="ea-quality">{quality.map(([label,value]) => { const pct = filtered.length ? Math.round(value/filtered.length*100) : 0; return <div key={label}><span>{label}<b>{filtered.length ? `${pct}%` : "—"}</b></span><i><em style={{ width: `${pct}%` }} /></i><small>{value} of {filtered.length} records</small></div>; })}</div></AnCard>
      </div>

      <AnCard title="Review operations" sub="Items currently waiting for a governed decision" action={<button className="ea-link" onClick={() => setPage("review-queue")}>Open review queue <Icon name="arrow-right" size={14} /></button>} className="ea-table-card">
        <div className="ea-table-wrap"><table className="ea-table"><thead><tr><th>Record</th><th>Type</th><th>Status</th><th>Priority</th><th>Reviewer</th><th>Updated</th></tr></thead><tbody>{queue.length ? queue.map((row) => <tr key={`${row.__kind}-${row.id}`}><td><strong>{row.name}</strong><small>{row.id}</small></td><td><span className="ea-type">{row.__kind}</span></td><td><span className="ea-status review">{String(row.status || "").replace(/-/g," ")}</span></td><td>{row.priority || "—"}</td><td>{row.reviewer && row.reviewer.name || "Unassigned"}</td><td>{row.updated || row.submitted || "—"}</td></tr>) : <tr><td colSpan="6"><div className="ea-empty"><Icon name="check-circle-2" size={20} /> No review items match these filters.</div></td></tr>}</tbody></table></div>
      </AnCard>

      {window.AnalyticsOperationsSections && <window.AnalyticsOperationsSections range={range} recipes={recipes} ingredients={ingredients} members={members} audit={audit} setPage={setPage} toast={toast} logExport={logExport} />}

      <div className="ea-grid ea-grid-roi">
        <AnCard title="ROI model" sub="Auditable scenario based on tenant output and your organization assumptions" className="ea-roi-card" action={<span className="ea-assumption-pill">Assumptions editable</span>}>
          <div className="ea-roi-inputs">
            <label><span>Minutes saved per released record</span><input type="number" min="0" value={roi.minutes} onChange={(e) => setRoiValue("minutes", e.target.value)} /><small>Organization estimate</small></label>
            <label><span>Loaded hourly labor cost</span><div><b>$</b><input type="number" min="0" value={roi.hourly} onChange={(e) => setRoiValue("hourly", e.target.value)} /></div><small>Salary + overhead</small></label>
            <label><span>Platform cost for this period</span><div><b>$</b><input type="number" min="0" value={roi.platform} onChange={(e) => setRoiValue("platform", e.target.value)} /></div><small>Use invoiced cost</small></label>
            <label><span>Scenario value per blocking finding</span><div><b>$</b><input type="number" min="0" value={roi.risk} onChange={(e) => setRoiValue("risk", e.target.value)} /></div><small>Optional, not booked savings</small></label>
          </div>
          <div className="ea-roi-results"><div><span>Estimated hours saved</span><strong>{roi.minutes ? hoursSaved.toFixed(1) + "h" : "—"}</strong><small>{released.length} released × {roi.minutes || "—"} min ÷ 60</small></div><div><span>Labor value</span><strong>{roi.minutes && roi.hourly ? anMoney(laborBenefit) : "—"}</strong><small>Hours saved × loaded hourly cost</small></div><div><span>Risk scenario</span><strong>{roi.risk && blockers.length ? anMoney(riskScenario) : "—"}</strong><small>{blockers.length} blocking findings × assumed value</small></div><div className="primary"><span>Net ROI</span><strong>{roiPercent == null ? "—" : `${roiPercent.toFixed(0)}%`}</strong><small>(Benefit − platform cost) ÷ platform cost</small></div><div><span>Net benefit</span><strong>{roi.platform && grossBenefit ? anMoney(netBenefit) : "—"}</strong><small>Gross benefit − platform cost</small></div><div><span>Payback</span><strong>{paybackDays == null ? "—" : `${paybackDays.toFixed(1)} days`}</strong><small>Platform cost ÷ period benefit</small></div></div>
          <div className="ea-roi-note"><Icon name="shield-check" size={15} /> ROI outputs remain blank until assumptions are entered. Scenario risk value is labeled separately from realized savings.</div>
        </AnCard>
        <AnCard title="Calculation ledger" sub="Every component behind the ROI result"><div className="ea-ledger">{[["Released records", released.length, "Tenant records"], ["Minutes per record", roi.minutes || "—", "Organization assumption"], ["Loaded hourly cost", roi.hourly ? anMoney(roi.hourly) : "—", "Organization assumption"], ["Blocking findings", blockers.length, activeRules.length ? "Rule engine" : "Not measured"], ["Labor benefit", roi.minutes && roi.hourly ? anMoney(laborBenefit) : "—", "Calculated"], ["Risk scenario", roi.risk && blockers.length ? anMoney(riskScenario) : "—", "Scenario only"], ["Platform cost", roi.platform ? anMoney(roi.platform) : "—", "Organization input"], ["Net benefit", roi.platform && grossBenefit ? anMoney(netBenefit) : "—", "Calculated"]].map(([label,value,source]) => <div key={label}><span>{label}<small>{source}</small></span><strong>{value}</strong></div>)}</div></AnCard>
      </div>

      <div className="ea-grid ea-grid-bottom">
        <AnCard title="Recent audit activity" sub="Live append-only workspace events" action={<button className="ea-link" onClick={() => setPage("audit")}>Full log <Icon name="arrow-up-right" size={14} /></button>}><div className="ea-audit-list">{audit.length ? audit.slice(0, 8).map((row,index) => <div key={index}><span className={`ea-severity ${row.severity || "low"}`} /><div><strong>{row.action || "activity"}</strong><p>{row.target || "Workspace event"}</p></div><span><b>{row.who || "System"}</b><small>{row.when || "—"}</small></span></div>) : <div className="ea-empty"><Icon name="scroll-text" size={20} /> No audited actions in this period.</div>}</div></AnCard>
        <AnCard id="ea-exports" title="Export center" sub="Download filtered data and retain an export trail" className="ea-export-card"><div id="ea-exports" className="ea-export-grid"><button onClick={() => exportData("records")}><Icon name="table-2" size={18} /><span><strong>Records CSV</strong><small>Spreadsheet-ready detail</small></span><Icon name="download" size={15} /></button><button onClick={() => exportData("audit")}><Icon name="scroll-text" size={18} /><span><strong>Audit CSV</strong><small>Actor and event log</small></span><Icon name="download" size={15} /></button><button onClick={() => exportData("json")}><Icon name="braces" size={18} /><span><strong>Analytics JSON</strong><small>Metrics, ROI, records, audit</small></span><Icon name="download" size={15} /></button><button onClick={() => exportData("print")}><Icon name="file-text" size={18} /><span><strong>Print / PDF</strong><small>Executive report layout</small></span><Icon name="printer" size={15} /></button></div><div className="ea-export-log"><h4>Export log</h4>{exportLog.length ? exportLog.slice(0,4).map((row,index) => <div key={index}><span>{row.type}</span><small>{row.rows} rows · {row.when}</small></div>) : <p>No exports generated yet.</p>}</div></AnCard>
      </div>
    </div>
  );
}

window.AnalyticsScreen = AnalyticsScreen;
