// =================================================================
// screens-credaxis.jsx — CredAxis domain screens (top-nav routes).
//
//   assessments   AssessmentsScreen   live: GET /tenants/{id}/assessments
//   tenants       TenantsScreen       live: GET /tenants (superadmin)
//   consultants   ConsultantsScreen   live: GET /consultants (superadmin)
//                                     live: GET /consultants/me/portfolio (consultant)
//   analytics     AnalyticsScreen     derived from live assessments
//
// Every screen tries the live API first and falls back to the bundled
// fixtures when the backend is unreachable, with a "Sample data" badge
// so the state is never ambiguous.
// =================================================================

// ---------- Backend → UI mappers ----------

const STATUS_TO_STAGE = {
  draft:        "Collecting",
  in_progress:  "AI Scoring",
  under_review: "Evidence Review",
  completed:    "Approved",
  archived:     "Archived",
};

const STAGE_TONE = {
  "Approved":        "good",
  "Evidence Review": "accent",
  "AI Scoring":      "accent",
  "Collecting":      "neutral",
  "Flagged":         "warn",
  "Archived":        "neutral",
};

const BAND_LABEL = {
  category_authority:     "Category Authority",
  emerging_authority:     "Emerging Authority",
  visible_underleveraged: "Visible but Underleveraged",
  low_trust_density:      "Low Trust Density",
  weak_authority:         "Weak Authority",
};

const scoreTone = (s) => (s >= 75 ? "good" : s >= 60 ? "accent" : s >= 50 ? "warn" : "bad");

const ScoreBadge = ({ score }) => {
  if (score == null) return <span style={{ color: "var(--muted)", fontSize: 12.5 }}>—</span>;
  const tone = scoreTone(score);
  const color = { good: "var(--good)", accent: "var(--accent)", warn: "var(--warn)", bad: "var(--bad)" }[tone];
  const soft  = { good: "var(--good-soft)", accent: "var(--accent-soft)", warn: "var(--warn-soft)", bad: "color-mix(in oklab, var(--bad) 12%, transparent)" }[tone];
  return (
    <span style={{
      display: "inline-flex", alignItems: "center", justifyContent: "center",
      minWidth: 38, padding: "3px 8px", borderRadius: 999,
      background: soft, color, fontFamily: "var(--mono)", fontSize: 12.5, fontWeight: 600,
      fontFeatureSettings: '"tnum"',
    }}>{Math.round(score)}</span>
  );
};

const fmtDate = (iso) => {
  if (!iso) return "—";
  try { return new Date(iso).toLocaleDateString("en-US", { month: "short", day: "numeric" }); }
  catch { return "—"; }
};

// ---------- Live-with-fallback fetch hook ----------
// Tries the live API; on any failure returns the fixture and live:false.
const useLive = (fetcher, fixture, deps = []) => {
  const [state, setState] = React.useState({ rows: null, live: null, loading: true });
  const refresh = React.useCallback(async () => {
    setState(s => ({ ...s, loading: true }));
    try {
      const rows = await fetcher();
      setState({ rows, live: true, loading: false });
    } catch (e) {
      setState({ rows: null, live: false, loading: false });
    }
  // eslint-disable-next-line
  }, deps);
  React.useEffect(() => { refresh(); }, [refresh]);
  React.useEffect(() => {
    const onTenant = () => refresh();
    window.addEventListener("tenant-changed", onTenant);
    return () => window.removeEventListener("tenant-changed", onTenant);
  }, [refresh]);
  // Only fall back to fixture after a confirmed API failure (live===false), not during loading.
  const rows = state.loading ? [] : (state.rows ?? (state.live === false ? fixture : []));
  return { rows, live: state.live === true, loading: state.loading, refresh };
};

const LiveBadge = ({ live, loading }) => (
  <StatusDot tone={loading ? "neutral" : live ? "good" : "warn"}>
    {loading ? "Loading…" : live ? "Live" : "Sample data"}
  </StatusDot>
);

// =================================================================
// AssessmentsScreen — /assessments
// =================================================================
const AssessmentsScreen = ({ data }) => {
  const [stage, setStage] = React.useState("All");
  const [query, setQuery] = React.useState("");

  const { rows, live, loading, refresh } = useLive(async () => {
    const [assessments, companies] = await Promise.all([
      window.api.tcall("listAssessments"),
      window.api.tcall("listCompanies"),
    ]);
    const companyName = Object.fromEntries((companies || []).map(c => [c.id, c.name]));
    return (assessments || []).map(a => ({
      id: a.id,
      subject: companyName[a.company_id] || a.company_id,
      tenant: "",                                   // current tenant context — implicit
      score: a.final_score,
      band: a.score_band ? (BAND_LABEL[a.score_band] || a.score_band) : null,
      stage: STATUS_TO_STAGE[a.status] || a.status,
      evidence: null,
      analyst: "",
      updated: fmtDate(a.completed_at || a.created_at),
    }));
  }, data.assessments || [], [window.session?.tenantId]);

  const stages = ["All", "Collecting", "AI Scoring", "Evidence Review", "Approved"];
  const filtered = rows.filter((a) =>
    (stage === "All" || a.stage === stage) &&
    (!query || ((a.subject || "") + (a.tenant || "") + (a.analyst || "")).toLowerCase().includes(query.toLowerCase()))
  );

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap)" }}>
      <ScreenHeader
        title="Assessments"
        subtitle="Authority assessments for the active client, from evidence collection to scoring."
        right={
          <span style={{ display: "inline-flex", gap: 10, alignItems: "center" }}>
            <LiveBadge live={live} loading={loading}/>
            <Btn kind="primary" icon={<IconChart size={14}/>} onClick={() => window.__nav("new-assessment")}>New assessment</Btn>
          </span>
        }
      />

      {/* Filters */}
      <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }}>
        <div style={{ width: 180 }}><Select value={stage} onChange={setStage} options={stages}/></div>
        <Input prefix={<IconSearch size={14}/>} placeholder="Search company…" value={query}
          onChange={(e) => setQuery(e.target.value)} style={{ width: 240 }}/>
        <span style={{ flex: 1 }}/>
        {!loading && <span style={{ fontSize: 12.5, color: "var(--muted)" }}>{filtered.length} result{filtered.length !== 1 ? "s" : ""}</span>}
      </div>

      <Card padded={false}>
        {loading ? (
          <div style={{ padding: "48px 20px", textAlign: "center", color: "var(--muted)", fontSize: 13.5 }}>Loading assessments…</div>
        ) : (
          <DataTable
            rows={filtered}
            keyField="id"
            rowsPerPage={10}
            defaultSort={{ key: "score", dir: "desc" }}
            onRowClick={(r) => live ? window.__nav("assessment-detail", r.id) : window.__toast("Detail view needs the live backend")}
            columns={[
              { key: "subject", label: "Company", render: (r) => <strong>{r.subject}</strong> },
              { key: "score",   label: "Score", align: "right", render: (r) => <ScoreBadge score={r.score}/> },
              { key: "band",    label: "Band", render: (r) => r.band
                  ? <span style={{ fontSize: 12.5 }}>{r.band}</span>
                  : <span style={{ color: "var(--muted)", fontSize: 12.5 }}>Not scored</span> },
              { key: "stage",   label: "Stage", render: (r) => <StatusDot tone={STAGE_TONE[r.stage] || "neutral"}>{r.stage}</StatusDot> },
              { key: "updated", label: "Updated", sortable: false, render: (r) => <span style={{ color: "var(--muted)", fontSize: 12.5 }}>{r.updated}</span> },
              { key: "_actions", label: "", sortable: false, render: (r) => (
                <button title="Open assessment" onClick={(e) => { e.stopPropagation(); if (live) window.__nav("assessment-detail", r.id); else window.__toast("Detail view needs the live backend"); }}
                  style={{ width: 28, height: 28, borderRadius: 6, border: "1px solid var(--line)", background: "var(--panel)", color: "var(--muted)", cursor: "pointer", fontSize: 13, display: "inline-flex", alignItems: "center", justifyContent: "center" }}>→</button>
              )},
            ]}
          />
        )}
      </Card>
    </div>
  );
};

// =================================================================
// TenantsScreen — /tenants  (superadmin)
// =================================================================
const TenantsScreen = ({ data }) => {
  const [query, setQuery] = React.useState("");
  const [statusFilter, setStatusFilter] = React.useState("All");

  const { rows, live, loading } = useLive(async () => {
    const tenants = await window.api.call("listTenants");
    return (tenants || []).map(t => ({
      id: t.id,
      name: t.name,
      industry: t.industry || "—",
      plan: t.plan,
      consultant: "—",
      assessments: null,
      avgScore: null,
      status: t.status === "active" ? "Active" : (t.status || "—"),
      since: t.slug,
    }));
  }, data.tenants || [], []);

  const filtered = rows.filter(r =>
    (statusFilter === "All" || r.status === statusFilter) &&
    (!query || r.name.toLowerCase().includes(query.toLowerCase()) || (r.industry || "").toLowerCase().includes(query.toLowerCase()))
  );

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap)" }}>
      <ScreenHeader
        title="Clients"
        subtitle="Client organizations on the CredAxis platform."
        right={
          <span style={{ display: "inline-flex", gap: 10, alignItems: "center" }}>
            <LiveBadge live={live} loading={loading}/>
            <Btn kind="primary" icon={<IconBuilding size={14}/>} onClick={() => window.__toast("Client onboarding arrives in Phase 3")}>Onboard client</Btn>
          </span>
        }
      />

      {/* Filters */}
      <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }}>
        <div style={{ width: 160 }}><Select value={statusFilter} onChange={setStatusFilter} options={["All", "Active", "Onboarding", "Inactive"]}/></div>
        <Input prefix={<IconSearch size={14}/>} placeholder="Search clients…" value={query}
          onChange={(e) => setQuery(e.target.value)} style={{ width: 240 }}/>
        <span style={{ flex: 1 }}/>
        {!loading && <span style={{ fontSize: 12.5, color: "var(--muted)" }}>{filtered.length} client{filtered.length !== 1 ? "s" : ""}</span>}
      </div>

      <Card padded={false}>
        {loading ? (
          <div style={{ padding: "48px 20px", textAlign: "center", color: "var(--muted)", fontSize: 13.5 }}>Loading clients…</div>
        ) : (
          <DataTable
            rows={filtered}
            keyField="id"
            defaultSort={{ key: "name", dir: "asc" }}
            onRowClick={(r) => { if (live) { window.session.setTenant(r.id); window.__toast(`Active client: ${r.name}`); } }}
            columns={[
              { key: "name",        label: "Client", render: (r) => (
                <span style={{ display: "flex", alignItems: "center", gap: 10 }}>
                  <Avatar name={r.name} size={26}/>
                  <strong>{r.name}</strong>
                </span>
              )},
              { key: "industry",    label: "Industry" },
              { key: "plan",        label: "Plan", render: (r) => r.plan
                  ? <span style={{ textTransform: "capitalize", fontSize: 13 }}>{r.plan}</span> : "—" },
              { key: "consultant",  label: "Consultant", render: (r) => r.consultant === "—"
                  ? <span style={{ color: "var(--warn)", fontSize: 13 }}>Unassigned</span>
                  : r.consultant },
              { key: "avgScore",    label: "Avg score", align: "right", render: (r) => <ScoreBadge score={r.avgScore}/> },
              { key: "status",      label: "Status", render: (r) => <StatusDot tone={r.status === "Active" ? "good" : "warn"}>{r.status}</StatusDot> },
            ]}
          />
        )}
      </Card>
    </div>
  );
};

// =================================================================
// ConsultantsScreen — /consultants  (superadmin)
// =================================================================
const ConsultantsScreen = ({ data }) => {
  const { rows, live, loading } = useLive(async () => {
    const consultants = await window.api.call("listConsultants");
    return (consultants || []).map(c => ({
      id: c.consultant_id,
      name: c.full_name,
      email: c.email,
      tenants: c.active_clients,
      active: null,
      completed: null,
      rating: null,
      status: c.active_clients > 0 ? "On engagement" : "Available",
      company: c.company_name,
    }));
  }, data.consultants || [], []);

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap)" }}>
      <ScreenHeader
        title="Consultants"
        subtitle="Roster, workload, and client coverage."
        right={
          <span style={{ display: "inline-flex", gap: 10, alignItems: "center" }}>
            <LiveBadge live={live} loading={loading}/>
            <Btn kind="primary" icon={<IconUsers size={14}/>} onClick={() => window.__nav("invite-member")}>Add consultant</Btn>
          </span>
        }
      />

      <div className="hx-cons-grid">
        {rows.map((c) => (
          <Card key={c.id}>
            <div style={{ display: "flex", gap: 12, alignItems: "center", marginBottom: 14 }}>
              <Avatar name={c.name} size={40}/>
              <div style={{ minWidth: 0 }}>
                <div style={{ fontWeight: 600, fontSize: 14.5 }}>{c.name}</div>
                <div style={{ color: "var(--muted)", fontSize: 12.5, overflow: "hidden", textOverflow: "ellipsis" }}>{c.email}</div>
              </div>
              <div style={{ marginLeft: "auto" }}>
                <StatusDot tone={c.status === "Available" ? "good" : c.status === "On engagement" ? "accent" : "warn"}>{c.status}</StatusDot>
              </div>
            </div>
            <KeyValueList items={[
              { k: "Clients assigned",   v: c.tenants != null ? String(c.tenants) : "—" },
              { k: "Firm",               v: c.company || "—" },
              { k: "Active assessments", v: c.active != null ? String(c.active) : "—" },
              { k: "Completed",          v: c.completed != null ? String(c.completed) : "—" },
            ]}/>
            <div style={{ marginTop: 14, display: "flex", gap: 8 }}>
              <Btn kind="secondary" size="sm" onClick={() => window.__toast("Assignment UI arrives in Phase 3")}>Assign client</Btn>
              <Btn kind="ghost" size="sm" onClick={() => window.__nav("members")}>View profile</Btn>
            </div>
          </Card>
        ))}
        {rows.length === 0 && !loading && (
          <Card><div style={{ color: "var(--muted)", fontSize: 13.5, padding: 8 }}>No consultants yet. Invite one with “Add consultant”.</div></Card>
        )}
      </div>

      <style>{`
        .hx-cons-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--gap); }
        @media (max-width: 980px) { .hx-cons-grid { grid-template-columns: 1fr; } }
      `}</style>
    </div>
  );
};

// =================================================================
// PortfolioScreen — consultant's multi-client command center.
// Rendered in place of the dashboard for the consultant role.
// =================================================================
const PortfolioScreen = () => {
  const { rows, live, loading } = useLive(async () => {
    const pf = await window.api.call("myPortfolio");
    return (pf?.clients || []).map(c => ({
      id: c.tenant_id,
      name: c.tenant_name,
      score: c.latest_score,
      delta: c.score_delta,
      band: c.score_band ? (BAND_LABEL[c.score_band] || c.score_band) : null,
      pendingTasks: c.pending_tasks,
      lastAssessed: fmtDate(c.last_assessed_at),
      scope: c.scope_notes,
    }));
  }, [], []);

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap)" }}>
      <ScreenHeader
        title="Client portfolio"
        subtitle="Your assigned clients — scores, momentum, and pending work."
        right={<LiveBadge live={live} loading={loading}/>}
      />

      <Card padded={false}>
        {loading ? (
          <div style={{ padding: "48px 20px", textAlign: "center", color: "var(--muted)", fontSize: 13.5 }}>Loading portfolio…</div>
        ) : rows.length === 0 ? (
          <div style={{ padding: "48px 20px", textAlign: "center", color: "var(--muted)", fontSize: 13.5 }}>
            {live ? "No clients assigned yet. Ask your administrator for an assignment." : "Backend offline — portfolio loads when connected."}
          </div>
        ) : (
          <DataTable
            rows={rows}
            keyField="id"
            defaultSort={{ key: "pendingTasks", dir: "desc" }}
            onRowClick={(r) => { window.session.setTenant(r.id); window.__nav("assessments"); }}
            columns={[
              { key: "name",  label: "Client", render: (r) => (
                <span style={{ display: "flex", alignItems: "center", gap: 10 }}>
                  <Avatar name={r.name} size={26}/><strong>{r.name}</strong>
                </span>
              )},
              { key: "score", label: "Score", align: "right", render: (r) => <ScoreBadge score={r.score}/> },
              { key: "delta", label: "Δ", align: "right", render: (r) => r.delta == null
                  ? <span style={{ color: "var(--muted)" }}>—</span>
                  : <span style={{ color: r.delta >= 0 ? "var(--good)" : "var(--bad)", fontFamily: "var(--mono)", fontSize: 12.5 }}>
                      {r.delta >= 0 ? "▲" : "▼"} {Math.abs(r.delta).toFixed(1)}
                    </span> },
              { key: "band",  label: "Band", render: (r) => r.band || <span style={{ color: "var(--muted)", fontSize: 12.5 }}>Not scored</span> },
              { key: "pendingTasks", label: "Pending tasks", align: "right", mono: true },
              { key: "lastAssessed", label: "Last assessed", sortable: false,
                render: (r) => <span style={{ color: "var(--muted)", fontSize: 12.5 }}>{r.lastAssessed}</span> },
            ]}
          />
        )}
      </Card>
    </div>
  );
};

// =================================================================
// AnalyticsScreen — /analytics
// =================================================================
// Stage + band colour maps shared by the analytics widgets.
const STAGE_COLORS = {
  "Approved": "var(--good)", "Evidence Review": "var(--accent)",
  "AI Scoring": "#7c5bf5", "Collecting": "var(--muted-2)", "Flagged": "var(--warn)", "Archived": "var(--muted-2)",
};
const BAND_COLORS = {
  category_authority:     "var(--good)",
  emerging_authority:     "var(--accent)",
  visible_underleveraged: "#7c5bf5",
  low_trust_density:      "var(--warn)",
  weak_authority:         "var(--bad)",
};

const AnalyticsScreen = ({ data }) => {
  const [companyId, setCompanyId] = React.useState("");

  // Offline/demo fixture shaped like the live overview payload.
  const fixture = {
    window_days: 30,
    company_id: null,
    companies: [],
    score_trend: [{
      company_id: "demo", company_name: "Portfolio", is_client: true,
      points: (data.scoreTrend || []).map((v, i) => ({ date: `d${i}`, total_score: v })),
    }],
    pipeline_by_stage: (data.assessments || []).reduce((acc, a) => {
      const s = a.status || "completed";
      const row = acc.find(r => r.status === s);
      if (row) row.count += 1; else acc.push({ status: s, count: 1 });
      return acc;
    }, []),
    throughput: (data.assessmentsByDay || []).map((v, i) => ({ date: `D${i + 1}`, count: v })),
    score_bands: [], score_composition: { common: 0, industry: 0, momentum: 0, final: 0, companies: 0 },
    top_movers: [], surface_coverage: { present: 0, in_progress: 0, not_present: 0, total: 0 },
  };

  const { rows, live, loading } = useLive(
    () => window.api.tcall("analyticsOverview", null, null,
      { qs: `?days=30${companyId ? `&company_id=${companyId}` : ""}` }),
    fixture,
    [window.session?.tenantId, companyId],
  );

  const ov = (rows && !Array.isArray(rows)) ? rows : fixture;

  // ---- Company selector ----
  const companyOpts = [{ label: "All companies", value: "" },
    ...(ov.companies || []).map(c => ({ label: c.is_client ? `${c.name} (client)` : c.name, value: c.id }))];

  // ---- Score trend → multi-series line ----
  const trendRows = (ov.score_trend || []).filter(r => (r.points || []).length >= 2);
  const trendSeries = trendRows.map(r => ({
    name: r.company_name,
    data: r.points.map(p => p.total_score ?? 0),
    color: r.is_client ? "var(--accent)" : "var(--muted-2)",
  }));

  // ---- Pipeline donut (map raw status → stage) ----
  const stageCounts = (ov.pipeline_by_stage || []).reduce((m, r) => {
    const stage = STATUS_TO_STAGE[r.status] || r.status;
    m[stage] = (m[stage] || 0) + r.count; return m;
  }, {});
  const totalAssessments = Object.values(stageCounts).reduce((s, v) => s + v, 0);
  const donut = Object.entries(stageCounts).map(([label, value]) => ({
    label, value, color: STAGE_COLORS[label] || "var(--muted-2)",
  }));

  // ---- Throughput bars ----
  const throughputBars = (ov.throughput || []).map(r => ({
    label: r.date.length > 5 ? r.date.slice(5) : r.date, value: r.count,
  }));

  // ---- Score-band distribution ----
  const bandBars = (ov.score_bands || []).map(r => ({
    label: BAND_LABEL[r.band] || r.band, value: r.count, color: BAND_COLORS[r.band] || "var(--muted-2)",
  }));

  // ---- Score composition (60/30/10) ----
  const comp = ov.score_composition || { common: 0, industry: 0, momentum: 0, final: 0 };
  const compBars = [
    { label: "Common authority", value: comp.common, color: "var(--accent)" },
    { label: "Industry authority", value: comp.industry, color: "#7c5bf5" },
    { label: "Momentum", value: comp.momentum, color: "var(--good)" },
  ];

  // ---- Top movers ----
  const movers = ov.top_movers || [];
  const topGains = movers.filter(m => m.delta > 0).slice(0, 5);
  const topDrops = movers.filter(m => m.delta < 0).slice(-5).reverse();

  // ---- Surface coverage ----
  const cov = ov.surface_coverage || { present: 0, in_progress: 0, not_present: 0, total: 0 };
  const coverageBars = [
    { label: "Present", value: cov.present, color: "var(--good)" },
    { label: "In progress", value: cov.in_progress, color: "var(--warn)" },
    { label: "Not present", value: cov.not_present, color: "var(--muted-2)" },
  ];

  const focusName = companyId ? (ov.companies || []).find(c => c.id === companyId)?.name : null;
  const lens = focusName || "all companies";

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap)" }}>
      <ScreenHeader title="Analytics" subtitle={`Authority trends and throughput for ${lens}.`}
        right={
          <div style={{ display: "flex", gap: 10, alignItems: "center" }}>
            <div style={{ width: 220 }}>
              <Select value={companyId} onChange={setCompanyId} options={companyOpts}/>
            </div>
            <LiveBadge live={live} loading={loading}/>
          </div>
        }/>

      <div className="hx-anal-grid">
        <Card title="Average score trend"
          subtitle={companyId ? "Selected company, last 30 days." : "Client vs. competitors, last 30 days."}>
          {trendSeries.length ? (
            <LineChart series={trendSeries} height={220} showArea={trendSeries.length === 1} showGrid showYAxis
              formatValue={(v) => v.toFixed(0)} axisLabels={["30d ago", "15d ago", "Today"]}/>
          ) : (
            <div style={{ height: 220, display: "flex", alignItems: "center", justifyContent: "center",
              color: "var(--muted)", fontSize: 13 }}>
              {loading ? "Loading…" : "No score history in this window yet."}
            </div>
          )}
        </Card>
        <Card title="Pipeline by stage" subtitle="Assessment distribution.">
          <div style={{ display: "flex", justifyContent: "center", padding: "8px 0" }}>
            <DonutChart size={170} thickness={22} data={donut}
              centerValue={String(totalAssessments)} centerLabel="assessments"/>
          </div>
        </Card>
      </div>

      <Card title="Daily throughput" subtitle="Assessments completed per day, last 30 days.">
        {throughputBars.length ? (
          <BarChart2 data={throughputBars} height={200} formatValue={(v) => v.toFixed(0)}/>
        ) : (
          <div style={{ height: 200, display: "flex", alignItems: "center", justifyContent: "center",
            color: "var(--muted)", fontSize: 13 }}>
            {loading ? "Loading…" : "No assessments completed in this window."}
          </div>
        )}
      </Card>

      <div className="hx-anal-grid">
        <Card title="Score-band distribution" subtitle="Where the client and its competitors sit.">
          {bandBars.length ? (
            <StackedBar data={bandBars} formatValue={(v) => String(v)}/>
          ) : (
            <div style={{ color: "var(--muted)", fontSize: 13, padding: "12px 0" }}>
              {loading ? "Loading…" : "No scored assessments yet."}
            </div>
          )}
        </Card>
        <Card title="Score composition"
          subtitle={companyId ? "Latest scored layers." : `Portfolio average · ${comp.companies || 0} companies.`}>
          <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
            <StackedBar data={compBars} total={100} formatValue={(v) => v.toFixed(1)}/>
            <div style={{ fontSize: 12.5, color: "var(--muted)" }}>
              Final score <strong style={{ color: "var(--ink-2)", fontFamily: "var(--mono)" }}>
              {(comp.final || 0).toFixed(1)}</strong> / 100 · max 60 / 30 / 10
            </div>
          </div>
        </Card>
      </div>

      <div className="hx-anal-grid">
        <Card title="Top movers" subtitle="Largest score changes over the window.">
          {(topGains.length || topDrops.length) ? (
            <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
              {[...topGains, ...topDrops].map(m => (
                <div key={m.company_id} style={{ display: "flex", alignItems: "center",
                  justifyContent: "space-between", gap: 12, fontSize: 13 }}>
                  <span style={{ color: "var(--ink-2)", overflow: "hidden", textOverflow: "ellipsis",
                    whiteSpace: "nowrap" }}>
                    {m.company_name}{m.is_client && <span style={{ color: "var(--muted)" }}> · client</span>}
                  </span>
                  <span style={{ display: "flex", alignItems: "center", gap: 10, flexShrink: 0 }}>
                    <span style={{ color: "var(--muted)", fontFamily: "var(--mono)", fontSize: 12 }}>
                      {m.from_score.toFixed(0)}→{m.to_score.toFixed(0)}</span>
                    <span style={{ fontFamily: "var(--mono)", fontWeight: 600,
                      color: m.delta >= 0 ? "var(--good)" : "var(--bad)" }}>
                      {m.delta >= 0 ? "+" : ""}{m.delta.toFixed(1)}</span>
                  </span>
                </div>
              ))}
            </div>
          ) : (
            <div style={{ color: "var(--muted)", fontSize: 13, padding: "12px 0" }}>
              {loading ? "Loading…" : "No score movement recorded in this window."}
            </div>
          )}
        </Card>
        <Card title="Authority surface coverage" subtitle={`${cov.present}/${cov.total} surfaces present.`}>
          {cov.total ? (
            <StackedBar data={coverageBars} formatValue={(v) => String(v)}/>
          ) : (
            <div style={{ color: "var(--muted)", fontSize: 13, padding: "12px 0" }}>
              {loading ? "Loading…" : "No authority surfaces assigned yet."}
            </div>
          )}
        </Card>
      </div>

      <style>{`
        .hx-anal-grid { display: grid; grid-template-columns: 1.4fr 1fr; gap: var(--gap); }
        @media (max-width: 1080px) { .hx-anal-grid { grid-template-columns: 1fr; } }
      `}</style>
    </div>
  );
};

// =================================================================
// AuditLogsScreen — settings rail.
// Superadmin sees the platform-wide trail; consultant/tenant-admin
// see the active tenant's trail.
// =================================================================
const AuditLogsScreen = () => {
  const [page, setPage] = React.useState(1);
  const [action, setAction] = React.useState("All");
  const role = window.session?.role;
  const isSuper = role === "superadmin";

  const ACTIONS = ["All", "create", "update", "delete", "login", "ai_task_run",
                   "score_override", "evidence_approve", "semrush_pull"];

  const { rows, live, loading } = useLive(async () => {
    const qs = `?page=${page}&page_size=25${action !== "All" ? `&action=${action}` : ""}`;
    return isSuper
      ? await window.api.call("allAuditLogs", null, null, { qs })
      : await window.api.tcall("tenantAuditLogs", null, null, { qs });
  }, { items: [], total: 0 }, [page, action, window.session?.tenantId]);

  const items = (rows?.items || []).map(l => ({
    id: l.id,
    when: l.timestamp ? new Date(l.timestamp).toLocaleString("en-US",
      { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit" }) : "—",
    actor: l.actor_role || "system",
    action: l.action,
    resource: l.resource_type ? `${l.resource_type}${l.resource_id ? ` · ${String(l.resource_id).slice(0, 8)}` : ""}` : "—",
    ip: l.ip_address || "—",
  }));

  const total = rows?.total || 0;
  const pages = Math.max(1, Math.ceil(total / 25));

  return (
    <div style={{ display: "flex", flexDirection: "column", gap: "var(--gap)" }}>
      <ScreenHeader
        title="Audit logs"
        subtitle={isSuper ? "Platform-wide activity trail." : "Activity trail for the active client."}
        right={<LiveBadge live={live} loading={loading}/>}
      />

      {/* Filters */}
      <div style={{ display: "flex", gap: 10, alignItems: "center", flexWrap: "wrap" }}>
        <div style={{ width: 200 }}><Select value={action} onChange={(a) => { setAction(a); setPage(1); }} options={ACTIONS}/></div>
        <span style={{ flex: 1 }}/>
        {!loading && (
          <span style={{ fontSize: 12.5, color: "var(--muted)" }}>
            {total > 0 ? `${total} entries · page ${page} of ${pages}` : live ? "No entries" : "Backend offline"}
          </span>
        )}
      </div>

      <Card padded={false}>
        {loading ? (
          <div style={{ padding: "48px 20px", textAlign: "center", color: "var(--muted)", fontSize: 13.5 }}>Loading audit logs…</div>
        ) : (
          <>
            <DataTable
              rows={items}
              keyField="id"
              columns={[
                { key: "when",     label: "When", render: (r) => <span style={{ fontFamily: "var(--mono)", fontSize: 12.5 }}>{r.when}</span> },
                { key: "actor",    label: "Actor role" },
                { key: "action",   label: "Action", render: (r) => <StatusDot tone={
                    r.action === "delete" ? "warn" : r.action === "ai_task_run" ? "accent" : "neutral"
                  }>{r.action}</StatusDot> },
                { key: "resource", label: "Resource", mono: true },
                { key: "ip",       label: "IP", mono: true },
              ]}
            />
            {pages > 1 && (
              <div style={{ display: "flex", gap: 8, padding: "10px 16px", justifyContent: "flex-end", borderTop: "1px solid var(--line-2)", background: "var(--panel-2)" }}>
                <Btn kind="ghost" size="sm" disabled={page <= 1} onClick={() => setPage(p => p - 1)}>← Previous</Btn>
                <Btn kind="ghost" size="sm" disabled={page >= pages} onClick={() => setPage(p => p + 1)}>Next →</Btn>
              </div>
            )}
          </>
        )}
      </Card>
    </div>
  );
};

// =================================================================
// SystemSettingsScreen — /system-settings  (superadmin only)
// =================================================================

const SettingRow = ({ label, description, children }) => (
  <div style={{
    display: "flex", alignItems: "center", justifyContent: "space-between",
    padding: "16px 0", borderBottom: "1px solid var(--line)",
    gap: 24,
  }}>
    <div style={{ flex: 1 }}>
      <div style={{ fontWeight: 500, marginBottom: 2 }}>{label}</div>
      {description && (
        <div style={{ fontSize: 13, color: "var(--muted)", lineHeight: 1.5 }}>
          {description}
        </div>
      )}
    </div>
    <div style={{ flexShrink: 0 }}>{children}</div>
  </div>
);

const ModeToggle = ({ headless, onChange, saving }) => {
  const active   = { background: "var(--accent)", color: "var(--accent-ink)", border: "none" };
  const inactive = { background: "var(--panel)", color: "var(--ink)", border: "1px solid var(--line)" };
  const base     = { padding: "7px 18px", borderRadius: 6, cursor: saving ? "not-allowed" : "pointer",
                     fontWeight: 500, fontSize: 13, transition: "all .15s", opacity: saving ? .6 : 1 };
  return (
    <div style={{ display: "flex", gap: 4, background: "var(--panel-2)", padding: 4, borderRadius: 8 }}>
      <button style={{ ...base, ...(headless ? inactive : active) }}
              disabled={saving} onClick={() => onChange(false)}>
        Named Chrome
      </button>
      <button style={{ ...base, ...(headless ? active : inactive) }}
              disabled={saving} onClick={() => onChange(true)}>
        Headless
      </button>
    </div>
  );
};

const SystemSettingsScreen = () => {
  const [settings, setSettings] = React.useState(null);
  const [saving, setSaving]     = React.useState(false);
  const [toast, setToast]       = React.useState(null);
  const [error, setError]       = React.useState(null);

  React.useEffect(() => {
    api.call("getSystemSettings")
      .then(d => setSettings(d))
      .catch(() => setError("Could not load settings — backend may be offline."));
  }, []);

  const showToast = (msg, kind = "success") => {
    setToast({ msg, kind });
    setTimeout(() => setToast(null), 3000);
  };

  const setPlaywrightHeadless = async (headless) => {
    setSaving(true);
    try {
      const updated = await api.call("updateSystemSettings", null, { playwright_headless: headless });
      setSettings(updated);
      showToast(headless
        ? "Switched to Headless mode — Chrome runs in background."
        : "Switched to Named Chrome — browser window opens during collection.");
    } catch (e) {
      showToast("Failed to save setting.", "error");
    } finally {
      setSaving(false);
    }
  };

  const setWaybackEnabled = async (enabled) => {
    setSaving(true);
    try {
      // body is the 3rd arg of api.call — the PUT /admin/settings handler stamps
      // wayback_effective_from server-side when enabling.
      const updated = await api.call("updateSystemSettings", null, { wayback_enabled: enabled });
      setSettings(updated);
      showToast(enabled
        ? "Wayback capture ON — every successful run is now archived."
        : "Wayback capture OFF — runs are no longer archived.");
    } catch (e) {
      showToast("Failed to save setting.", "error");
    } finally {
      setSaving(false);
    }
  };

  return (
    <div style={{ maxWidth: 760, margin: "0 auto", padding: "32px 24px" }}>
      <ScreenHeader
        icon={<IconSettings size={22}/>}
        title="System Settings"
        subtitle="Platform-wide configuration. Visible to superadmins only."
      />

      {error && <Banner kind="error" style={{ marginBottom: 20 }}>{error}</Banner>}

      {toast && (
        <div style={{
          position: "fixed", bottom: 28, right: 28, zIndex: 9999,
          background: toast.kind === "error" ? "var(--bad)" : "var(--good)",
          color: "#fff", padding: "12px 20px", borderRadius: 8,
          boxShadow: "0 4px 16px rgba(0,0,0,.18)", fontSize: 14, fontWeight: 500,
        }}>
          {toast.msg}
        </div>
      )}

      <Card style={{ padding: "0 24px", marginBottom: 24 }}>
        <div style={{ padding: "12px 0 4px", fontWeight: 600, fontSize: 12,
                      color: "var(--muted)", textTransform: "uppercase", letterSpacing: .6 }}>
          Evidence Collection
        </div>

        <SettingRow
          label="Playwright Chrome mode"
          description={
            settings?.playwright_headless
              ? "Headless — Chrome runs in background with no visible window. Best for servers and CI."
              : "Named Chrome — browser window is visible during collection. Allows you to log in to LinkedIn, Glassdoor, Instagram etc. and have sessions saved for future runs."
          }
        >
          {settings === null ? (
            <div style={{ color: "var(--muted)", fontSize: 13 }}>Loading…</div>
          ) : (
            <ModeToggle
              headless={!!settings.playwright_headless}
              onChange={setPlaywrightHeadless}
              saving={saving}
            />
          )}
        </SettingRow>

        {settings && !settings.playwright_headless && (
          <div style={{
            margin: "12px 0 16px",
            background: "var(--panel-2)",
            border: "1px solid var(--line)",
            borderRadius: 8, padding: "14px 16px",
            fontSize: 13, color: "var(--muted)", lineHeight: 1.7,
          }}>
            <strong style={{ color: "var(--ink)" }}>Session setup (one-time):</strong>
            {" "}Chrome profile is stored at <code style={{ background:"var(--panel)",
            padding:"1px 5px", borderRadius:4 }}>~/.credaxis/chrome-profile</code>.
            Run the first collection, log in to any platform that opens, and sessions are saved automatically for all future runs.
          </div>
        )}
      </Card>

      <Card style={{ padding: "0 24px", marginBottom: 24 }}>
        <div style={{ padding: "12px 0 4px", fontWeight: 600, fontSize: 12,
                      color: "var(--muted)", textTransform: "uppercase", letterSpacing: .6 }}>
          Scoring-run history (Wayback)
        </div>
        <SettingRow
          label="Wayback capture"
          description={
            settings?.wayback_enabled
              ? `On — every successful scoring run is archived${settings?.wayback_effective_from ? ` since ${String(settings.wayback_effective_from).slice(0,10)}` : ""}. Runs before that are not captured.`
              : "Off — scoring runs are not archived. Turn on when you're done testing; capture begins from the moment you enable it (client and peer brands alike)."
          }
        >
          {settings === null ? (
            <div style={{ color: "var(--muted)", fontSize: 13 }}>Loading…</div>
          ) : (
            <div style={{ display: "flex", gap: 4, background: "var(--panel-2)", padding: 4, borderRadius: 8 }}>
              <button style={{ padding: "7px 18px", borderRadius: 6, fontWeight: 500, fontSize: 13,
                cursor: saving ? "not-allowed" : "pointer", opacity: saving ? .6 : 1, transition: "all .15s",
                ...(settings.wayback_enabled ? { background: "var(--panel)", color: "var(--ink)", border: "1px solid var(--line)" } : { background: "var(--accent)", color: "var(--accent-ink)", border: "none" }) }}
                disabled={saving} onClick={() => setWaybackEnabled(false)}>Off</button>
              <button style={{ padding: "7px 18px", borderRadius: 6, fontWeight: 500, fontSize: 13,
                cursor: saving ? "not-allowed" : "pointer", opacity: saving ? .6 : 1, transition: "all .15s",
                ...(settings.wayback_enabled ? { background: "var(--accent)", color: "var(--accent-ink)", border: "none" } : { background: "var(--panel)", color: "var(--ink)", border: "1px solid var(--line)" }) }}
                disabled={saving} onClick={() => setWaybackEnabled(true)}>On</button>
            </div>
          )}
        </SettingRow>
      </Card>

      <Card style={{ padding: "0 24px" }}>
        <div style={{ padding: "12px 0 4px", fontWeight: 600, fontSize: 12,
                      color: "var(--muted)", textTransform: "uppercase", letterSpacing: .6 }}>
          API Keys status
        </div>
        {[
          { label: "Google API Key",  key: "GOOGLE_API_KEY",   desc: "PageSpeed · YouTube · Google Places" },
          { label: "OpenAI API Key",  key: "OPENAI_API_KEY",   desc: "Action plans · gap narratives · investor summary" },
          { label: "News API Key",    key: "NEWS_API_KEY",      desc: "Media mentions · financial news" },
          { label: "SEMrush API Key", key: "SEMRUSH_API_KEY",   desc: "Market visibility · content freshness" },
          { label: "GitHub Token",    key: "GITHUB_TOKEN",      desc: "Higher rate limits for repo evidence" },
        ].map(({ label, desc }) => (
          <SettingRow key={label} label={label} description={desc}>
            <span style={{
              fontSize: 12, fontWeight: 600, padding: "3px 10px", borderRadius: 12,
              background: "var(--panel-2)", color: "var(--muted)",
            }}>
              Set in .env
            </span>
          </SettingRow>
        ))}
      </Card>
    </div>
  );
};

Object.assign(window, {
  AssessmentsScreen, TenantsScreen, ConsultantsScreen, AnalyticsScreen, PortfolioScreen, AuditLogsScreen,
  SystemSettingsScreen,
  // shared helpers for screens-workflow.jsx
  ScoreBadge, STATUS_TO_STAGE, BAND_LABEL, LiveBadge, useLive,
});
