// Settings pages: Configuration, Period & Calendar, Users & Roles, Customization
// All four live under the "Settings" group in the sidebar.

const { useState: useStateSet, useEffect: useEffectSet } = React;

// ────────────────────────────────────────────────────────────────────────
// CONFIGURATION — integrations, Excel import, AI mapping rules
// ────────────────────────────────────────────────────────────────────────
function ConfigPage({ data, bizType, setBizType, onRerunWizard, companyProfile, scopedCompanyId }) {
  const [tab, setTab] = useStateSet("sources");
  // Resolve companyId: use scoped (admin viewing a customer) or look up from session
  const [resolvedCompanyId, setResolvedCompanyId] = useStateSet(scopedCompanyId || companyProfile?.id || null);

  useEffectSet(() => {
    if (resolvedCompanyId) return;
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      const { data: { session } } = await db.auth.getSession();
      if (!session) return;
      const { data: m } = await db.from("company_users").select("company_id").eq("user_id", session.user.id).eq("status", "Active").maybeSingle();
      if (m?.company_id) setResolvedCompanyId(m.company_id);
    })();
  }, []);

  return (
    <div className="pc-page">
      <SourcesTabStats companyId={resolvedCompanyId} />

      <div className="pc-section-tabs">
        {[
          { k: "sources", l: "Data sources" },
          { k: "import",  l: "Excel / CSV import" },
          { k: "mapping", l: "Account mapping" },
          { k: "alerts",  l: "Sync & alerts" },
        ].map(t => (
          <button key={t.k} className={tab === t.k ? "active" : ""} onClick={() => setTab(t.k)}>{t.l}</button>
        ))}
        <div style={{ flex: 1 }} />
        <button className="pc-btn-mini ghost" onClick={onRerunWizard}>Re-run setup wizard</button>
      </div>

      {tab === "sources" && <SourcesTab companyId={resolvedCompanyId} />}
      {tab === "import"  && <ImportTab bizType={bizType} />}
      {tab === "mapping" && <MappingTab companyId={resolvedCompanyId} />}
      {tab === "alerts"  && <AlertsTab />}
    </div>
  );
}

// KPI header that loads real counts from DB
function SourcesTabStats({ companyId }) {
  const [stats, setStats] = useStateSet(null);

  useEffectSet(() => {
    if (!companyId) return;
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      const { data: integs } = await db.from("integrations").select("id, provider, status, last_sync_at").eq("company_id", companyId);
      const { data: txns } = await db.from("gl_transactions").select("id", { count: "exact", head: true }).eq("company_id", companyId);
      const { data: mappings } = await db.from("account_mappings").select("id", { count: "exact", head: true }).eq("company_id", companyId);
      const connected = (integs || []).filter(i => i.status === "active" || i.status === "connected");
      const lastSync = connected.length > 0
        ? connected.map(i => i.last_sync_at).filter(Boolean).sort().reverse()[0]
        : null;
      const lastSyncLabel = lastSync
        ? (() => {
            const mins = Math.round((Date.now() - new Date(lastSync)) / 60000);
            if (mins < 2) return "Just now";
            if (mins < 60) return `${mins} min ago`;
            return `${Math.round(mins/60)}h ago`;
          })()
        : "Never";
      setStats({
        connected: connected.length,
        total: (integs || []).length,
        txns: txns?.length || 0,
        mappings: mappings?.length || 0,
        lastSync: lastSyncLabel,
      });
    })();
  }, [companyId]);

  if (!stats) {
    return (
      <div className="pc-kpi-grid pc-kpi-grid-4">
        <KPICard label="Data sources connected" value="—" hint="Loading…" accent="var(--positive)" />
        <KPICard label="GL transactions" value="—" hint="Loading…" accent="var(--positive)" />
        <KPICard label="Last sync" value="—" hint="Loading…" accent="var(--accent)" />
        <KPICard label="Account mappings" value="—" hint="Loading…" accent="var(--accent-2)" />
      </div>
    );
  }

  return (
    <div className="pc-kpi-grid pc-kpi-grid-4">
      <KPICard label="Data sources connected" value={stats.connected > 0 ? `${stats.connected} of ${stats.total}` : "None yet"} hint={stats.connected > 0 ? "Live" : "Connect an integration below"} accent={stats.connected > 0 ? "var(--positive)" : "var(--warning)"} />
      <KPICard label="GL transactions" value={stats.txns > 0 ? stats.txns.toLocaleString() : "None yet"} hint={stats.txns > 0 ? "Imported" : "Connect accounting software below"} accent="var(--positive)" />
      <KPICard label="Last sync" value={stats.lastSync} hint="Auto-syncs hourly when connected" accent="var(--accent)" />
      <KPICard label="Account mappings" value={stats.mappings > 0 ? stats.mappings : "None yet"} hint={stats.mappings > 0 ? "AI mapped" : "Generated after first sync"} accent="var(--accent-2)" />
    </div>
  );
}

const ALL_INTEGRATIONS = [
  { k: "qbo",       n: "QuickBooks Online", d: "Primary accounting — P&L, balance sheet, GL detail",  status: "available", cat: "Accounting", primary: true },
  { k: "xero",      n: "Xero",             d: "Primary accounting or secondary source",                status: "available", cat: "Accounting", primary: true },
  { k: "netsuite",  n: "NetSuite",         d: "Enterprise GL · SuiteTalk REST API",                   status: "available", cat: "Accounting", primary: true },
  { k: "sage",      n: "Sage Intacct",     d: "Beta — request access",                                status: "beta",      cat: "Accounting", primary: true },
  { k: "dynamics",  n: "Microsoft Dynamics", d: "Beta — request access",                              status: "beta",      cat: "Accounting", primary: false },
  { k: "stripe",    n: "Stripe",           d: "Payment, payout, and customer-level revenue",           status: "available", cat: "Payments",   primary: false },
  { k: "shopify",   n: "Shopify",          d: "Order-level revenue, inventory sync",                   status: "available", cat: "Commerce",   primary: false },
  { k: "salesforce",n: "Salesforce",       d: "Pipeline, deals, customer lifecycle",                   status: "available", cat: "CRM",        primary: false },
  { k: "hubspot",   n: "HubSpot",          d: "Deals, contacts, MQLs",                                status: "available", cat: "CRM",        primary: false },
  { k: "gusto",     n: "Gusto / Rippling", d: "Payroll, headcount, benefits",                         status: "available", cat: "HR",         primary: false },
  { k: "bill",      n: "Bill.com",         d: "AP automation, vendor payments",                        status: "available", cat: "Payments",   primary: false },
  { k: "csv",       n: "Excel / CSV upload", d: "Manual import — see Import tab",                     status: "available", cat: "Manual",     primary: false },
  { k: "bank",      n: "Bank feed",        d: "Plaid · cash transactions",                             status: "available", cat: "Banking",    primary: false },
];

function SourcesTab({ companyId }) {
  const [dbIntegrations, setDbIntegrations] = useStateSet([]); // from DB
  const [loadingDb, setLoadingDb] = useStateSet(true);
  const [connecting, setConnecting] = useStateSet(null);
  const [requested, setRequested] = useStateSet({});
  const [disconnecting, setDisconnecting] = useStateSet(null);
  const [syncingKey, setSyncingKey] = useStateSet(null);
  const [notification, setNotification] = useStateSet(null);

  const showNotice = (msg, type = "info") => {
    setNotification({ msg, type });
    setTimeout(() => setNotification(null), 4000);
  };

  const loadIntegrations = async () => {
    if (!companyId) { setLoadingDb(false); return; }
    const db = window.supabaseClient;
    if (!db) { setLoadingDb(false); return; }
    const { data } = await db.from("integrations").select("id, provider, status, connected_at, last_sync_at, provider_meta").eq("company_id", companyId);
    setDbIntegrations(data || []);
    setLoadingDb(false);
  };

  useEffectSet(() => { loadIntegrations(); }, [companyId]);

  const connectedMap = {};
  dbIntegrations.forEach(i => { connectedMap[i.provider] = i; });

  const handleRequestAccess = (integ) => {
    setRequested(r => ({ ...r, [integ.k]: true }));
    showNotice(`Request sent for ${integ.n}. We'll email you when access is ready.`, "success");
  };

  const handleConnect = (integ) => {
    if (!companyId) {
      showNotice("No company selected. Please contact support.", "error");
      return;
    }
    setConnecting(integ);
  };

  const handleConnected = async (providerKey) => {
    setConnecting(null);
    await loadIntegrations();
    showNotice(`${ALL_INTEGRATIONS.find(i=>i.k===providerKey)?.n || providerKey} connected successfully.`, "success");
  };

  const handleDisconnect = async (providerKey) => {
    setDisconnecting(null);
    const db = window.supabaseClient;
    if (!db || !companyId) return;
    await db.from("integrations").update({ status: "disconnected" }).eq("company_id", companyId).eq("provider", providerKey);
    await loadIntegrations();
    showNotice("Integration disconnected. Historical data is retained.", "info");
  };

  const handleSyncNow = async (providerKey, providerName) => {
    setSyncingKey(providerKey);
    const db = window.supabaseClient;
    try {
      const { data: { session } } = await db.auth.getSession();
      const token = session?.access_token;
      const syncFns = { shopify: "sync-shopify", stripe: "sync-stripe" };
      const fnSlug = syncFns[providerKey];
      if (fnSlug) {
        const res = await fetch(`${window.SUPABASE_URL}/functions/v1/${fnSlug}`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
            "Authorization": `Bearer ${token}`,
            "Apikey": window.SUPABASE_ANON_KEY,
          },
          body: JSON.stringify({ companyId }),
        });
        const result = await res.json();
        if (!res.ok) throw new Error(result.error || "Sync failed");
        const parts = [];
        if (result.ordersCreated) parts.push(`${result.ordersCreated} orders`);
        if (result.productsUpserted) parts.push(`${result.productsUpserted} products`);
        if (result.subscriptionsUpserted) parts.push(`${result.subscriptionsUpserted} subscriptions`);
        if (result.customersUpserted) parts.push(`${result.customersUpserted} customers`);
        const detail = parts.length ? ` — ${parts.join(", ")} synced` : "";
        showNotice(`${providerName} sync complete${detail}.`, "success");
      } else {
        // Non-sync providers: just mark as synced
        await db.from("integrations").update({ last_sync_at: new Date().toISOString() }).eq("company_id", companyId).eq("provider", providerKey);
        showNotice(`${providerName} sync started. Data will refresh within the hour.`, "success");
      }
    } catch (err) {
      showNotice(`Sync failed: ${err.message}`, "error");
    } finally {
      setSyncingKey(null);
      await loadIntegrations();
    }
  };

  const activeConnections = dbIntegrations.filter(i => i.status === "active" || i.status === "connected");
  const pendingConnections = dbIntegrations.filter(i => i.status === "pending_setup");

  return (
    <>
      {notification && (
        <div style={{
          position: "fixed", top: 60, right: 20, zIndex: 9998,
          background: notification.type === "success" ? "var(--positive)" : notification.type === "error" ? "var(--danger)" : "var(--accent)",
          color: "white", padding: "10px 18px", borderRadius: 8, fontSize: 13, fontWeight: 500,
          boxShadow: "0 4px 16px rgba(0,0,0,0.2)", maxWidth: 360,
        }}>
          {notification.msg}
        </div>
      )}

      {loadingDb ? (
        <Card><div style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>Loading integrations…</div></Card>
      ) : activeConnections.length === 0 && pendingConnections.length === 0 ? (
        <Card title="No integrations connected yet" subtitle="Connect your accounting software to start seeing real data">
          <div style={{ padding: "12px 0 4px", display: "flex", gap: 10, flexWrap: "wrap" }}>
            {ALL_INTEGRATIONS.filter(i => i.primary && i.status === "available").map(i => (
              <button key={i.k} className="pc-btn-mini" onClick={() => handleConnect(i)}>
                <SystemLogo k={i.k} size={18} />
                <span style={{ marginLeft: 6 }}>Connect {i.n}</span>
              </button>
            ))}
          </div>
        </Card>
      ) : (
        <>
          {activeConnections.map(row => {
            const def = ALL_INTEGRATIONS.find(i => i.k === row.provider) || { k: row.provider, n: row.provider, cat: "Unknown" };
            const lastSync = row.last_sync_at
              ? (() => {
                  const mins = Math.round((Date.now() - new Date(row.last_sync_at)) / 60000);
                  if (mins < 2) return "Just now";
                  if (mins < 60) return `${mins} min ago`;
                  return `${Math.round(mins/60)}h ago`;
                })()
              : "Not synced yet";
            return (
              <Card key={row.id} title={def.cat === "Accounting" ? "Accounting system" : def.cat} subtitle="Primary source of financial data">
                <div className="pc-source-row">
                  <SystemLogo k={row.provider} />
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 14, fontWeight: 600 }}>
                      {def.n}
                      <span className="pc-conn-badge" style={{ marginLeft: 8 }}><span className="pc-conn-dot"></span> Connected</span>
                    </div>
                    {row.provider_meta?.tenant && (
                      <div style={{ fontSize: 11.5, color: "var(--text-3)", marginTop: 3 }}>
                        <b>{row.provider_meta.tenant}</b>
                      </div>
                    )}
                    <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 2 }}>
                      Last sync: {lastSync} · Connected {row.connected_at ? new Date(row.connected_at).toLocaleDateString() : "recently"}
                    </div>
                  </div>
                  <div style={{ display: "flex", gap: 6 }}>
                    <button
                      className="pc-btn-mini ghost"
                      disabled={syncingKey === row.provider}
                      onClick={() => handleSyncNow(row.provider, def.n)}
                    >
                      {syncingKey === row.provider ? "Syncing…" : "Sync now"}
                    </button>
                    <button className="pc-btn-mini ghost" style={{ color: "var(--danger)" }} onClick={() => setDisconnecting(row.provider)}>
                      Disconnect
                    </button>
                  </div>
                </div>
              </Card>
            );
          })}
          {pendingConnections.map(row => {
            const def = ALL_INTEGRATIONS.find(i => i.k === row.provider) || { k: row.provider, n: row.provider };
            return (
              <Card key={row.id} title="Pending connection">
                <div className="pc-source-row">
                  <SystemLogo k={row.provider} />
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 14, fontWeight: 600 }}>{def.n} <span style={{ fontSize: 12, color: "var(--warning)", fontWeight: 500 }}>· Setup in progress</span></div>
                    <div style={{ fontSize: 11.5, color: "var(--text-3)", marginTop: 3 }}>OAuth authorization not yet completed</div>
                  </div>
                  <div style={{ display: "flex", gap: 6 }}>
                    <button className="pc-btn-mini" onClick={() => handleConnect(def)}>Complete setup</button>
                    <button className="pc-btn-mini ghost" style={{ color: "var(--danger)" }} onClick={() => handleDisconnect(row.provider)}>Cancel</button>
                  </div>
                </div>
              </Card>
            );
          })}
        </>
      )}

      <Card title="Available integrations" subtitle="Connect additional data sources">
        <div className="pc-integration-grid">
          {ALL_INTEGRATIONS.filter(i => !connectedMap[i.k] || connectedMap[i.k]?.status === "disconnected").map(i => {
            const isRequested = !!requested[i.k];
            return (
              <div key={i.k} className="pc-integ-card">
                <div style={{ display: "flex", alignItems: "center", gap: 10, marginBottom: 8 }}>
                  <SystemLogo k={i.k} />
                  <div style={{ flex: 1 }}>
                    <div style={{ fontSize: 12.5, fontWeight: 600 }}>{i.n}</div>
                    <div style={{ fontSize: 10, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.4 }}>{i.cat}</div>
                  </div>
                </div>
                <div style={{ fontSize: 11.5, color: "var(--text-3)", lineHeight: 1.4, marginBottom: 10, minHeight: 30 }}>{i.d}</div>
                <button
                  className={"pc-btn-mini " + (i.status === "beta" || isRequested ? "ghost" : "")}
                  style={{ width: "100%", justifyContent: "center" }}
                  onClick={() => {
                    if (isRequested) return;
                    if (i.status === "beta") { handleRequestAccess(i); return; }
                    handleConnect(i);
                  }}
                  disabled={isRequested}
                >
                  {isRequested ? "Request sent" : i.status === "beta" ? "Request access" : "Connect"}
                </button>
              </div>
            );
          })}
        </div>
      </Card>

      {connecting && (
        <ConnectIntegrationModal
          integration={connecting}
          companyId={companyId}
          onClose={() => setConnecting(null)}
          onConnected={handleConnected}
        />
      )}

      {disconnecting && (
        <div className="pc-modal-backdrop" onClick={() => setDisconnecting(null)}>
          <div className="pc-modal" style={{ maxWidth: 440 }} onClick={e => e.stopPropagation()}>
            <div className="pc-modal-hd">
              <div style={{ fontSize: 15, fontWeight: 600 }}>Disconnect integration?</div>
              <button className="pc-icon-btn" onClick={() => setDisconnecting(null)}><Icon d={icons.x} size={14} /></button>
            </div>
            <div className="pc-modal-body">
              <div style={{ fontSize: 13, lineHeight: 1.6 }}>
                Your historical data will be retained but no longer refreshed. You can reconnect anytime.
              </div>
            </div>
            <div style={{ padding: "14px 18px", borderTop: "1px solid var(--border)", display: "flex", justifyContent: "flex-end", gap: 8 }}>
              <button className="pc-btn ghost" onClick={() => setDisconnecting(null)}>Cancel</button>
              <button className="pc-btn" style={{ background: "var(--danger)", color: "white", borderColor: "var(--danger)" }} onClick={() => handleDisconnect(disconnecting)}>
                Disconnect
              </button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

// Providers that use standard OAuth redirect (vs API key entry)
const OAUTH_PROVIDERS = ["xero", "qbo", "hubspot", "stripe", "shopify"];
// Providers that need an API key / manual credentials instead
const APIKEY_PROVIDERS = ["netsuite", "salesforce", "gusto", "bill", "bank"];

function ConnectIntegrationModal({ integration, companyId, onClose, onConnected }) {
  const [phase, setPhase] = useStateSet("ready"); // ready | redirecting | waiting | not_configured | error | apikey
  const [errorMsg, setErrorMsg] = useStateSet("");
  const [shopDomain, setShopDomain] = useStateSet("");
  const [apiKeyFields, setApiKeyFields] = useStateSet({});

  useEffectSet(() => {
    const onKey = (e) => { if (e.key === "Escape" && phase === "ready") onClose(); };
    window.addEventListener("keydown", onKey);
    return () => window.removeEventListener("keydown", onKey);
  }, [onClose, phase]);

  // Handle ?oauth_success / ?oauth_error on return from provider
  useEffectSet(() => {
    const params = new URLSearchParams(window.location.search);
    const success = params.get("oauth_success");
    const err = params.get("oauth_error");
    if (success === integration.k) {
      // Clean URL then notify parent
      window.history.replaceState({}, "", window.location.pathname);
      onConnected(integration.k);
    } else if (err) {
      window.history.replaceState({}, "", window.location.pathname);
      setErrorMsg(decodeURIComponent(err));
      setPhase("error");
    }
  }, []);

  const supabaseUrl = window.supabaseClient?.supabaseUrl || "";
  const oauthFnUrl = supabaseUrl.replace(/\/$/, "") + "/functions/v1/oauth-connect";

  const startOAuth = async () => {
    if (!companyId) { setErrorMsg("No company context. Please reload and try again."); setPhase("error"); return; }
    setPhase("redirecting");
    try {
      const db = window.supabaseClient;
      const { data: { session } } = await db.auth.getSession();
      const token = session?.access_token;

      let endpoint = oauthFnUrl;
      let body = { provider: integration.k, companyId };

      if (integration.k === "shopify") {
        if (!shopDomain.trim()) { setErrorMsg("Enter your Shopify store domain first."); setPhase("ready"); return; }
        endpoint = oauthFnUrl + "/shopify";
        body = { companyId, shopDomain: shopDomain.trim() };
      }

      const res = await fetch(endpoint, {
        method: "POST",
        headers: { "Content-Type": "application/json", "Authorization": `Bearer ${token}` },
        body: JSON.stringify(body),
      });
      const data = await res.json();

      if (data.error === "not_configured") {
        setErrorMsg(data.message || "Integration not yet configured.");
        setPhase("not_configured");
        return;
      }
      if (data.error) throw new Error(data.error);

      // Redirect user to provider's login page
      window.location.href = data.authUrl;
    } catch (e) {
      setErrorMsg(e.message || "Failed to start OAuth. Please try again.");
      setPhase("error");
    }
  };

  const saveApiKey = async () => {
    if (!companyId) { setErrorMsg("No company context."); setPhase("error"); return; }
    setPhase("redirecting");
    try {
      const db = window.supabaseClient;
      const { error } = await db.from("integrations").upsert({
        company_id: companyId,
        provider: integration.k,
        status: "pending_setup",
        credentials: apiKeyFields,
        provider_meta: { auth_type: "apikey", configured_at: new Date().toISOString() },
        connected_at: new Date().toISOString(),
      }, { onConflict: "company_id,provider" });
      if (error) throw error;
      onConnected(integration.k);
    } catch (e) {
      setErrorMsg(e.message || "Failed to save credentials.");
      setPhase("error");
    }
  };

  const isOAuth = OAUTH_PROVIDERS.includes(integration.k);

  const API_KEY_CONFIGS = {
    netsuite:   [{ k: "accountId", l: "Account ID" }, { k: "consumerKey", l: "Consumer Key" }, { k: "consumerSecret", l: "Consumer Secret" }, { k: "tokenId", l: "Token ID" }, { k: "tokenSecret", l: "Token Secret" }],
    salesforce: [{ k: "instanceUrl", l: "Instance URL (e.g. https://yourorg.salesforce.com)" }, { k: "clientId", l: "Connected App Client ID" }, { k: "clientSecret", l: "Connected App Client Secret" }],
    gusto:      [{ k: "apiKey", l: "Gusto API Key" }],
    bill:       [{ k: "orgId", l: "Organisation ID" }, { k: "devKey", l: "Developer Key" }, { k: "sessionId", l: "Session ID" }],
    bank:       [{ k: "plaidClientId", l: "Plaid Client ID" }, { k: "plaidSecret", l: "Plaid Secret" }],
  };

  return (
    <div className="pc-modal-backdrop" onClick={phase === "ready" ? onClose : undefined}>
      <div className="pc-modal" style={{ maxWidth: 520 }} onClick={(e) => e.stopPropagation()}>
        <div className="pc-modal-hd">
          <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
            <SystemLogo k={integration.k} />
            <div>
              <div style={{ fontSize: 11, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>Connect integration</div>
              <div style={{ fontSize: 16, fontWeight: 600 }}>{integration.n}</div>
            </div>
          </div>
          {(phase === "ready" || phase === "not_configured" || phase === "error" || phase === "apikey") && (
            <button className="pc-icon-btn" onClick={onClose}><Icon d={icons.x} size={14} /></button>
          )}
        </div>

        <div className="pc-modal-body">

          {/* ── Ready: OAuth ── */}
          {phase === "ready" && isOAuth && (
            <>
              <div style={{ fontSize: 13.5, lineHeight: 1.6, marginBottom: 16 }}>
                Clicking <b>Connect {integration.n}</b> will open {integration.n}'s login page in this tab. Sign in with your {integration.n} credentials and approve read-only access. You'll be returned here automatically.
              </div>
              <div style={{ padding: "12px 14px", background: "var(--bg-elev-1)", border: "1px solid var(--border)", borderRadius: 6, fontSize: 12, color: "var(--text-2)", lineHeight: 1.55, marginBottom: integration.k === "shopify" ? 12 : 16 }}>
                <div style={{ fontSize: 10.5, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5, marginBottom: 6 }}>Read-only access</div>
                Perdura requests read-only permission to your {integration.n} data. We never write back and you can revoke access from {integration.n} at any time.
              </div>
              {integration.k === "shopify" && (
                <div style={{ marginBottom: 16 }}>
                  <label style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)", display: "block", marginBottom: 6 }}>Your Shopify store domain</label>
                  <input
                    className="pc-period-select"
                    style={{ width: "100%", fontSize: 13 }}
                    placeholder="yourstore.myshopify.com"
                    value={shopDomain}
                    onChange={e => setShopDomain(e.target.value)}
                  />
                </div>
              )}
              <div style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
                <button className="pc-btn ghost" onClick={onClose}>Cancel</button>
                <button className="pc-btn primary" onClick={startOAuth}>
                  Connect {integration.n} →
                </button>
              </div>
            </>
          )}

          {/* ── Ready: API Key ── */}
          {phase === "ready" && !isOAuth && (
            <>
              <div style={{ fontSize: 13.5, lineHeight: 1.6, marginBottom: 16 }}>
                {integration.n} uses API key authentication. Enter your credentials below — they are stored encrypted and used only to pull read-only data.
              </div>
              {(API_KEY_CONFIGS[integration.k] || []).map(f => (
                <div key={f.k} style={{ marginBottom: 12 }}>
                  <label style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)", display: "block", marginBottom: 5 }}>{f.l}</label>
                  <input
                    className="pc-period-select"
                    type={f.k.toLowerCase().includes("secret") || f.k.toLowerCase().includes("key") ? "password" : "text"}
                    style={{ width: "100%", fontSize: 13 }}
                    placeholder={f.l}
                    value={apiKeyFields[f.k] || ""}
                    onChange={e => setApiKeyFields(prev => ({ ...prev, [f.k]: e.target.value }))}
                  />
                </div>
              ))}
              <div style={{ display: "flex", gap: 8, justifyContent: "flex-end", marginTop: 8 }}>
                <button className="pc-btn ghost" onClick={onClose}>Cancel</button>
                <button
                  className="pc-btn primary"
                  disabled={!(API_KEY_CONFIGS[integration.k] || []).every(f => apiKeyFields[f.k]?.trim())}
                  onClick={saveApiKey}
                >
                  Save &amp; connect
                </button>
              </div>
            </>
          )}

          {/* ── Redirecting ── */}
          {phase === "redirecting" && (
            <div style={{ display: "flex", flexDirection: "column", alignItems: "center", padding: "32px 16px", gap: 14 }}>
              <div className="pc-spinner" style={{ width: 32, height: 32, borderWidth: 3 }} />
              <div style={{ fontSize: 14, fontWeight: 500 }}>
                {isOAuth ? `Redirecting to ${integration.n}…` : "Saving credentials…"}
              </div>
              <div style={{ fontSize: 12, color: "var(--text-3)" }}>
                {isOAuth ? "You will be taken to the login page." : "Verifying your API keys."}
              </div>
            </div>
          )}

          {/* ── Not configured ── */}
          {phase === "not_configured" && (
            <div style={{ padding: "8px 0" }}>
              <div style={{ display: "flex", alignItems: "flex-start", gap: 12, padding: "14px", background: "rgba(251,191,36,0.08)", border: "1px solid rgba(251,191,36,0.25)", borderRadius: 8, marginBottom: 16 }}>
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="#d97706" strokeWidth="2" strokeLinecap="round" style={{ flexShrink: 0, marginTop: 1 }}><circle cx="12" cy="12" r="10"/><line x1="12" y1="8" x2="12" y2="12"/><line x1="12" y1="16" x2="12.01" y2="16"/></svg>
                <div style={{ fontSize: 13, lineHeight: 1.6 }}>{errorMsg}</div>
              </div>
              <div style={{ fontSize: 12.5, color: "var(--text-2)", lineHeight: 1.6, marginBottom: 16 }}>
                To enable {integration.n}, the platform administrator needs to register a developer app at <b>{integration.n === "Xero" ? "developer.xero.com" : integration.n === "QuickBooks Online" ? "developer.intuit.com" : "the provider's developer portal"}</b> and add the OAuth credentials as environment secrets.
              </div>
              <div style={{ display: "flex", justifyContent: "flex-end" }}>
                <button className="pc-btn ghost" onClick={onClose}>Close</button>
              </div>
            </div>
          )}

          {/* ── Error ── */}
          {phase === "error" && (
            <div style={{ padding: "8px 0" }}>
              <div style={{ fontSize: 13, color: "var(--danger)", background: "rgba(239,68,68,0.06)", border: "1px solid rgba(239,68,68,0.2)", borderRadius: 8, padding: "12px 14px", marginBottom: 16, lineHeight: 1.55 }}>
                {errorMsg}
              </div>
              <div style={{ display: "flex", justifyContent: "flex-end", gap: 8 }}>
                <button className="pc-btn ghost" onClick={onClose}>Cancel</button>
                <button className="pc-btn primary" onClick={() => setPhase("ready")}>Try again</button>
              </div>
            </div>
          )}

        </div>
      </div>
    </div>
  );
}

function SystemLogo({ k, size = 32 }) {
  const styles = {
    qbo:      { bg: "#2ca01c", t: "qb",  c: "white" },
    xero:     { bg: "#13b5ea", t: "X",   c: "white" },
    netsuite: { bg: "#125ca0", t: "NS",  c: "white" },
    sage:     { bg: "#00d639", t: "S",   c: "white" },
    dynamics: { bg: "#0067b8", t: "D",   c: "white" },
    stripe:   { bg: "#635bff", t: "$",   c: "white" },
    shopify:  { bg: "#96bf48", t: "S",   c: "white" },
    salesforce: { bg: "#00a1e0", t: "SF", c: "white" },
    hubspot:  { bg: "#ff7a59", t: "H",   c: "white" },
    gusto:    { bg: "#f45d48", t: "G",   c: "white" },
    bill:     { bg: "#1a73e8", t: "B",   c: "white" },
    bank:     { bg: "#22c55e", t: "🏦",  c: "white" },
    csv:      { bg: "rgba(15,23,42,0.08)", t: "csv", c: "var(--text-2)" },
  };
  const s = styles[k] || styles.csv;
  return (
    <div style={{
      width: size, height: size, borderRadius: 6, background: s.bg,
      display: "flex", alignItems: "center", justifyContent: "center",
      fontSize: 11, fontWeight: 700, color: s.c, letterSpacing: -0.2, flexShrink: 0,
    }}>
      {s.t}
    </div>
  );
}

function ImportTab({ bizType }) {
  const templates = {
    common: [
      { name: "Chart of accounts",        desc: "GL account list with classification", rows: 248, schema: "AcctCode, Name, Class, Subclass, Department, Active" },
      { name: "Trial balance (period)",   desc: "Monthly balances by account",          rows: 248, schema: "AcctCode, Period, DebitBalance, CreditBalance, NetChange" },
      { name: "GL detail (transactions)", desc: "Line-level transactions",              rows: 14392, schema: "Date, AcctCode, Memo, Reference, Debit, Credit, Class, Customer, Vendor" },
      { name: "Customers",                desc: "Master customer list",                 rows: 84, schema: "CustomerID, Name, Segment, Region, Terms, CreditLimit, Since" },
      { name: "Vendors",                  desc: "Master vendor list",                   rows: 38, schema: "VendorID, Name, Country, Terms, LeadTime, PreferredPayment" },
      { name: "AR aging snapshot",        desc: "Open invoices with days overdue",      rows: 81, schema: "Invoice, Customer, IssueDate, DueDate, Amount, AmountPaid, DaysOverdue" },
      { name: "AP aging snapshot",        desc: "Open bills with days outstanding",     rows: 73, schema: "Bill, Vendor, IssueDate, DueDate, Amount, AmountPaid, DaysOutstanding" },
    ],
    product: [
      { name: "Items / SKUs",             desc: "Product master with cost + price",     rows: 12, schema: "SKU, Name, Category, UnitCost, UnitPrice, OnHand, ReorderPoint, Vendor" },
      { name: "Sales order detail",       desc: "Line-level sales transactions",        rows: 4218, schema: "Order, Date, Customer, SKU, Qty, UnitPrice, ExtPrice, Channel" },
      { name: "Purchase orders",          desc: "Open and recent POs",                  rows: 142, schema: "PO, Date, Vendor, SKU, Qty, UnitCost, ExpectedDate, Status" },
    ],
    manufacturing: [
      { name: "Bill of materials (BOM)",  desc: "Components per finished good",         rows: 240, schema: "FinishedSKU, ComponentSKU, QtyPer, UoM, ScrapAllowance" },
      { name: "Production orders",        desc: "Work orders + run completion",         rows: 318, schema: "WorkOrder, SKU, QtyPlanned, QtyProduced, ScrapQty, Start, End" },
      { name: "Machine downtime log",     desc: "Unplanned + planned downtime events",   rows: 1840, schema: "Date, Line, Machine, Reason, Minutes, ShiftLeader" },
    ],
    service: [
      { name: "Time entries",             desc: "Billable + non-billable time",         rows: 8420, schema: "Date, Resource, Project, ServiceCode, Hours, Billable, Rate" },
      { name: "Projects / engagements",   desc: "Master project list",                  rows: 38, schema: "ProjectID, Customer, Type, BookedValue, StartDate, EndDate, ProjectMgr" },
      { name: "Resources",                desc: "Staff with role + cost rate",          rows: 10, schema: "ResourceID, Name, Role, BillRate, CostRate, Capacity" },
    ],
    retail: [
      { name: "Store master",             desc: "Locations with sqft, hours, FTE",      rows: 9,    schema: "StoreID, Name, Region, Sqft, Hours, FTE, OpenedDate, RentMonthly" },
      { name: "Store revenue daily",       desc: "Daily sales by store + category",      rows: 2840, schema: "Date, StoreID, Category, GrossSales, Discounts, Net, TransCount" },
      { name: "Foot traffic",              desc: "Daily traffic counts by store",         rows: 2840, schema: "Date, StoreID, Visitors, ConvertedTxns" },
      { name: "Inventory by store",         desc: "Store-level stock snapshots",           rows: 108,  schema: "Date, StoreID, SKU, OnHand, UnitCost, RetailPrice" },
    ],
  };
  const businessTemplates = templates[bizType] || templates.product;
  const allTemplates = [...templates.common, ...businessTemplates];

  return (
    <>
      <div className="pc-ai-banner">
        <div style={{ display: "flex", alignItems: "flex-start", gap: 14, flex: 1, minWidth: 0 }}>
          <div style={{ width: 36, height: 36, borderRadius: 10, background: "radial-gradient(circle at 30% 30%, var(--accent), var(--accent-2))", display: "flex", alignItems: "center", justifyContent: "center", flexShrink: 0 }}>
            <Icon d={icons.upload} size={18} stroke="var(--on-accent)" strokeWidth={2.4} />
          </div>
          <div>
            <div style={{ fontSize: 11, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.6, marginBottom: 3 }}>For businesses without QuickBooks, Xero, or NetSuite</div>
            <div style={{ fontSize: 14, color: "var(--text)", lineHeight: 1.5 }}>
              Download our Excel templates, populate them with your data, and upload. Perdura's AI will validate, map accounts, and populate every dashboard — same as a live integration. Templates auto-adapt to your business type: <b>{bizType === "service" ? "Service" : bizType === "manufacturing" ? "Manufacturing" : "Product"}</b>.
            </div>
          </div>
        </div>
      </div>

      <Card title="Available templates" subtitle={`${allTemplates.length} templates · tailored for your business type`}
            action={<button className="pc-btn-mini">Download all as zip</button>} padding={0}>
        <table className="pc-table">
          <thead>
            <tr>
              <th>Template</th>
              <th>Description</th>
              <th>Required columns</th>
              <th style={{textAlign:"right"}}>Sample rows</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            {allTemplates.map((t, i) => (
              <tr key={i}>
                <td style={{paddingLeft:14, fontWeight: 500}}>
                  <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                    <div style={{ width: 24, height: 28, background: "linear-gradient(180deg, #1d6f42, #185730)", borderRadius: 3, display: "flex", alignItems: "center", justifyContent: "center", color: "white", fontSize: 9, fontWeight: 700 }}>X</div>
                    {t.name}
                  </div>
                </td>
                <td style={{fontSize: 12, color: "var(--text-2)"}}>{t.desc}</td>
                <td style={{fontFamily: "ui-monospace, monospace", fontSize: 11, color: "var(--text-3)"}}>{t.schema}</td>
                <td style={{fontFamily: "ui-monospace, monospace", textAlign: "right", fontSize: 11.5, color: "var(--text-2)"}}>{t.rows.toLocaleString()}</td>
                <td style={{display: "flex", gap: 6, justifyContent: "flex-end", paddingRight: 14}}>
                  <button className="pc-btn-mini ghost" onClick={() => exportRows(t.name.replace(/\W+/g, "_"), [{ Note: "Replace this row with your data — schema: " + t.schema }], t.name)}>Template</button>
                  <button className="pc-btn-mini">Upload</button>
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </Card>

      <div className="pc-grid-2">
        <Card title="Import history" subtitle="Most recent uploads">
          <table className="pc-table compact">
            <thead><tr><th>File</th><th>Type</th><th>Status</th><th>Date</th></tr></thead>
            <tbody>
              {[
                { f: "Apr_2026_TB.xlsx",        t: "Trial Balance",  s: "Processed", d: "May 02" },
                { f: "Q1_GL_detail.csv",        t: "GL Detail",      s: "Processed", d: "Apr 05" },
                { f: "Customer_master_v3.xlsx", t: "Customers",      s: "Processed", d: "Mar 12" },
                { f: "Inventory_snapshot.xlsx", t: "Items / SKUs",   s: "1 warning", d: "Mar 12" },
              ].map((r, i) => (
                <tr key={i}>
                  <td style={{paddingLeft: 14, fontFamily: "ui-monospace, monospace", fontSize: 11.5}}>{r.f}</td>
                  <td><span className="pc-chip">{r.t}</span></td>
                  <td><StatusPill s={r.s.includes("warning") ? "Open" : "Paid"} /></td>
                  <td style={{fontSize: 11.5, color: "var(--text-3)"}}>{r.d}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </Card>
        <Card title="Drag a file to upload" subtitle="Or click to browse">
          <div className="pc-dropzone">
            <Icon d={icons.upload} size={28} stroke="var(--text-3)" />
            <div style={{ fontSize: 13, fontWeight: 500, marginTop: 10 }}>Drop your Excel or CSV here</div>
            <div style={{ fontSize: 11.5, color: "var(--text-3)", marginTop: 4, textAlign: "center" }}>We'll detect the schema automatically.<br />Supports .xlsx, .xls, .csv up to 100MB.</div>
            <button className="pc-btn-mini" style={{ marginTop: 12 }}>Choose file</button>
          </div>
        </Card>
      </div>
    </>
  );
}

const MAPPING_CATEGORIES = [
  "Revenue",
  "Contra-revenue",
  "COGS",
  "Gross Profit",
  "Opex / S&M",
  "Opex / R&D",
  "Opex / G&A",
  "Opex / Travel",
  "Opex / Software",
  "Opex / Payroll",
  "Other Income",
  "Other Expense",
  "Tax",
  "Balance Sheet / Asset",
  "Balance Sheet / Liability",
  "Balance Sheet / Equity",
  "Ignore / Exclude",
];

function MappingTab({ companyId }) {
  const [rows, setRows] = useStateSet([]);
  const [loading, setLoading] = useStateSet(true);
  const [editing, setEditing] = useStateSet(null); // { id, account_code, account_name, canonical_category, subcategory, source, confidence }
  const [saving, setSaving] = useStateSet(false);
  const [search, setSearch] = useStateSet("");
  const [notification, setNotification] = useStateSet(null);
  const [glSummary, setGlSummary] = useStateSet([]); // { account_code, account_name, txn_count, total }

  const showNotice = (msg, type = "success") => {
    setNotification({ msg, type });
    setTimeout(() => setNotification(null), 3500);
  };

  const loadMappings = async (cid) => {
    if (!cid) { setLoading(false); return; }
    const db = window.supabaseClient;
    if (!db) { setLoading(false); return; }
    const { data } = await db
      .from("account_mappings")
      .select("id, account_code, account_name, canonical_category, subcategory, source, confidence, updated_at")
      .eq("company_id", cid)
      .order("account_code", { ascending: true });
    setRows(data || []);
    setLoading(false);

    // Load GL transaction summary grouped by account for the "unmapped" section
    const { data: txns } = await db
      .from("gl_transactions")
      .select("account_code, account_name, amount")
      .eq("company_id", cid);
    if (txns) {
      const grouped = {};
      txns.forEach(t => {
        if (!grouped[t.account_code]) grouped[t.account_code] = { account_code: t.account_code, account_name: t.account_name, txn_count: 0, total: 0 };
        grouped[t.account_code].txn_count++;
        grouped[t.account_code].total += parseFloat(t.amount) || 0;
      });
      setGlSummary(Object.values(grouped));
    }
  };

  // Resolve companyId from prop or session
  const [resolvedCid, setResolvedCid] = useStateSet(companyId || null);
  useEffectSet(() => {
    if (companyId) { setResolvedCid(companyId); return; }
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      const { data: { session } } = await db.auth.getSession();
      if (!session) return;
      const { data: m } = await db.from("company_users").select("company_id").eq("user_id", session.user.id).eq("status", "Active").maybeSingle();
      if (m?.company_id) setResolvedCid(m.company_id);
    })();
  }, [companyId]);

  useEffectSet(() => { if (resolvedCid) loadMappings(resolvedCid); }, [resolvedCid]);

  const saveEdit = async () => {
    if (!editing || !resolvedCid) return;
    setSaving(true);
    const db = window.supabaseClient;
    const now = new Date().toISOString();
    if (editing.id) {
      // Update existing
      await db.from("account_mappings").update({
        canonical_category: editing.canonical_category,
        subcategory: editing.subcategory || null,
        source: "User · overridden",
        updated_at: now,
      }).eq("id", editing.id);
      setRows(prev => prev.map(r => r.id === editing.id
        ? { ...r, canonical_category: editing.canonical_category, subcategory: editing.subcategory, source: "User · overridden", updated_at: now }
        : r
      ));
    } else {
      // Insert new mapping
      const { data: inserted } = await db.from("account_mappings").insert({
        company_id: resolvedCid,
        account_code: editing.account_code,
        account_name: editing.account_name,
        canonical_category: editing.canonical_category,
        subcategory: editing.subcategory || null,
        source: "User · manual",
        confidence: 100,
        updated_at: now,
        created_at: now,
      }).select().single();
      if (inserted) setRows(prev => [...prev, inserted].sort((a, b) => (a.account_code || "").localeCompare(b.account_code || "")));
    }
    setSaving(false);
    setEditing(null);
    showNotice("Mapping saved.");
  };

  const deleteMapping = async (id) => {
    const db = window.supabaseClient;
    await db.from("account_mappings").delete().eq("id", id);
    setRows(prev => prev.filter(r => r.id !== id));
    showNotice("Mapping removed.");
  };

  const filtered = rows.filter(r => {
    if (!search) return true;
    const q = search.toLowerCase();
    return (r.account_code || "").toLowerCase().includes(q) || (r.account_name || "").toLowerCase().includes(q) || (r.canonical_category || "").toLowerCase().includes(q);
  });

  const mappedCodes = new Set(rows.map(r => r.account_code));
  const unmapped = glSummary.filter(g => !mappedCodes.has(g.account_code));

  if (loading) {
    return <Card><div style={{ padding: 32, textAlign: "center", color: "var(--text-3)" }}>Loading account mappings…</div></Card>;
  }

  return (
    <>
      {notification && (
        <div style={{
          position: "fixed", top: 60, right: 20, zIndex: 9998,
          background: notification.type === "success" ? "var(--positive)" : "var(--danger)",
          color: "white", padding: "10px 18px", borderRadius: 8, fontSize: 13, fontWeight: 500,
          boxShadow: "0 4px 16px rgba(0,0,0,0.2)",
        }}>
          {notification.msg}
        </div>
      )}

      {rows.length === 0 && unmapped.length === 0 ? (
        <Card>
          <div style={{ padding: "40px 24px", textAlign: "center" }}>
            <div style={{ fontSize: 15, fontWeight: 600, marginBottom: 8 }}>No GL accounts yet</div>
            <div style={{ fontSize: 13, color: "var(--text-2)", maxWidth: 400, margin: "0 auto 20px", lineHeight: 1.6 }}>
              Connect an accounting integration or import a trial balance to generate account mappings. The AI will classify each GL account automatically.
            </div>
            <button className="pc-btn-mini" onClick={() => {}}>Go to Data Sources</button>
          </div>
        </Card>
      ) : (
        <>
          <Card title="Account mappings" subtitle={`${rows.length} mapped · ${unmapped.length} unmapped · how GL accounts roll up to P&L categories`}
                action={
                  <div style={{ display: "flex", gap: 8, alignItems: "center" }}>
                    <input
                      className="pc-period-select"
                      style={{ minWidth: 200 }}
                      placeholder="Search accounts…"
                      value={search}
                      onChange={e => setSearch(e.target.value)}
                    />
                    <ExportButton
                      rows={filtered.map(r => ({ Code: r.account_code, Name: r.account_name, Category: r.canonical_category, Subcategory: r.subcategory || "", Source: r.source, Confidence: r.confidence }))}
                      filename="account_mappings"
                    />
                    <button className="pc-btn-mini" onClick={() => setEditing({ id: null, account_code: "", account_name: "", canonical_category: "Revenue", subcategory: "" })}>
                      + Add mapping
                    </button>
                  </div>
                } padding={0}>
            <table className="pc-table">
              <thead>
                <tr>
                  <th>Account</th>
                  <th>Category</th>
                  <th>Subcategory</th>
                  <th>Source</th>
                  <th style={{ textAlign: "right" }}>Confidence</th>
                  <th></th>
                </tr>
              </thead>
              <tbody>
                {filtered.map((r) => (
                  <tr key={r.id}>
                    <td style={{ paddingLeft: 14 }}>
                      <div style={{ fontFamily: "ui-monospace, monospace", fontSize: 11, color: "var(--text-3)" }}>{r.account_code}</div>
                      <div style={{ fontSize: 12.5, fontWeight: 500 }}>{r.account_name}</div>
                    </td>
                    <td style={{ fontSize: 12.5 }}>{r.canonical_category}</td>
                    <td style={{ fontSize: 12, color: "var(--text-2)" }}>{r.subcategory || <span style={{ color: "var(--text-4)" }}>—</span>}</td>
                    <td style={{ fontSize: 11.5, color: r.source?.includes("User") ? "var(--warning)" : "var(--text-2)" }}>{r.source}</td>
                    <td style={{ textAlign: "right" }}>
                      {r.confidence != null ? <ConfBar v={parseFloat(r.confidence)} /> : <span style={{ fontSize: 11, color: "var(--text-4)" }}>—</span>}
                    </td>
                    <td style={{ textAlign: "right", paddingRight: 14 }}>
                      <div style={{ display: "inline-flex", gap: 4 }}>
                        <button className="pc-btn-mini ghost" onClick={() => setEditing({ ...r })}>Edit</button>
                        <button className="pc-btn-mini ghost" style={{ color: "var(--danger)" }} onClick={() => deleteMapping(r.id)}>Remove</button>
                      </div>
                    </td>
                  </tr>
                ))}
                {filtered.length === 0 && (
                  <tr><td colSpan={6} style={{ padding: 24, textAlign: "center", color: "var(--text-3)" }}>No accounts match.</td></tr>
                )}
              </tbody>
            </table>
          </Card>

          {unmapped.length > 0 && (
            <Card title={`${unmapped.length} unmapped GL accounts`} subtitle="These accounts appear in your transactions but have no mapping rule"
                  padding={0}>
              <table className="pc-table">
                <thead>
                  <tr>
                    <th>Account</th>
                    <th style={{ textAlign: "right" }}>Transactions</th>
                    <th style={{ textAlign: "right" }}>Net balance</th>
                    <th></th>
                  </tr>
                </thead>
                <tbody>
                  {unmapped.map((g, i) => (
                    <tr key={i}>
                      <td style={{ paddingLeft: 14 }}>
                        <div style={{ fontFamily: "ui-monospace, monospace", fontSize: 11, color: "var(--text-3)" }}>{g.account_code}</div>
                        <div style={{ fontSize: 12.5, fontWeight: 500 }}>{g.account_name}</div>
                      </td>
                      <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace", fontSize: 12 }}>{g.txn_count.toLocaleString()}</td>
                      <td style={{ textAlign: "right", fontFamily: "ui-monospace, monospace", fontSize: 12, color: g.total >= 0 ? "var(--positive)" : "var(--danger)" }}>
                        {g.total < 0 ? "-" : ""}${Math.abs(g.total).toLocaleString("en-US", { minimumFractionDigits: 0, maximumFractionDigits: 0 })}
                      </td>
                      <td style={{ textAlign: "right", paddingRight: 14 }}>
                        <button className="pc-btn-mini"
                          onClick={() => setEditing({ id: null, account_code: g.account_code, account_name: g.account_name, canonical_category: "Revenue", subcategory: "" })}>
                          Map account
                        </button>
                      </td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </Card>
          )}
        </>
      )}

      {editing && (
        <div className="pc-modal-backdrop" onClick={() => setEditing(null)}>
          <div className="pc-modal" style={{ maxWidth: 520 }} onClick={e => e.stopPropagation()}>
            <div className="pc-modal-hd">
              <div>
                <div style={{ fontSize: 11, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>
                  {editing.id ? "Edit mapping" : "Add mapping"}
                </div>
                <div style={{ fontSize: 16, fontWeight: 600 }}>
                  {editing.id ? (editing.account_code + " · " + editing.account_name) : "New account mapping"}
                </div>
              </div>
              <button className="pc-icon-btn" onClick={() => setEditing(null)}><Icon d={icons.x} size={14} /></button>
            </div>
            <div className="pc-modal-body">
              {!editing.id && (
                <>
                  <div style={{ marginBottom: 12 }}>
                    <label style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)", display: "block", marginBottom: 5 }}>Account code</label>
                    <input
                      className="pc-period-select"
                      style={{ width: "100%", fontSize: 13 }}
                      placeholder="e.g. 4000"
                      value={editing.account_code}
                      onChange={e => setEditing(prev => ({ ...prev, account_code: e.target.value }))}
                    />
                  </div>
                  <div style={{ marginBottom: 12 }}>
                    <label style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)", display: "block", marginBottom: 5 }}>Account name</label>
                    <input
                      className="pc-period-select"
                      style={{ width: "100%", fontSize: 13 }}
                      placeholder="e.g. Product Sales – Online"
                      value={editing.account_name}
                      onChange={e => setEditing(prev => ({ ...prev, account_name: e.target.value }))}
                    />
                  </div>
                </>
              )}
              <div style={{ marginBottom: 12 }}>
                <label style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)", display: "block", marginBottom: 5 }}>P&L category</label>
                <select
                  className="pc-period-select"
                  style={{ width: "100%", fontSize: 13 }}
                  value={editing.canonical_category}
                  onChange={e => setEditing(prev => ({ ...prev, canonical_category: e.target.value }))}
                >
                  {MAPPING_CATEGORIES.map(c => <option key={c} value={c}>{c}</option>)}
                </select>
              </div>
              <div style={{ marginBottom: 20 }}>
                <label style={{ fontSize: 12, fontWeight: 600, color: "var(--text-2)", display: "block", marginBottom: 5 }}>
                  Subcategory <span style={{ fontWeight: 400, color: "var(--text-3)" }}>(optional)</span>
                </label>
                <input
                  className="pc-period-select"
                  style={{ width: "100%", fontSize: 13 }}
                  placeholder="e.g. DTC, Performance marketing, Freight-in…"
                  value={editing.subcategory || ""}
                  onChange={e => setEditing(prev => ({ ...prev, subcategory: e.target.value }))}
                />
              </div>
              {editing.id && (
                <div style={{ padding: "10px 12px", background: "rgba(251,191,36,0.08)", border: "1px solid rgba(251,191,36,0.2)", borderRadius: 6, fontSize: 12, color: "var(--text-2)", lineHeight: 1.55 }}>
                  Editing this will mark the mapping as "User · overridden" and override any AI classification. You can remove the mapping to let AI re-classify it.
                </div>
              )}
            </div>
            <div style={{ padding: "14px 18px", borderTop: "1px solid var(--border)", display: "flex", justifyContent: "flex-end", gap: 8 }}>
              <button className="pc-btn ghost" onClick={() => setEditing(null)}>Cancel</button>
              <button
                className="pc-btn primary"
                disabled={saving || !editing.canonical_category || (!editing.id && (!editing.account_code.trim() || !editing.account_name.trim()))}
                onClick={saveEdit}
              >
                {saving ? "Saving…" : "Save mapping"}
              </button>
            </div>
          </div>
        </div>
      )}
    </>
  );
}

function AlertsTab() {
  return (
    <>
      <Card title="Sync schedule" subtitle="When Perdura pulls fresh data">
        <div className="pc-form-grid">
          <Field label="Sync frequency">
            <select defaultValue="Hourly">
              <option>Real-time (live)</option>
              <option>Hourly</option>
              <option>Every 4 hours</option>
              <option>Daily at 6am</option>
              <option>Manual only</option>
            </select>
          </Field>
          <Field label="Sync window">
            <select defaultValue="Off-hours">
              <option>Anytime</option>
              <option>Off-hours (10pm – 6am)</option>
              <option>Business hours only</option>
            </select>
          </Field>
          <Field label="History depth">
            <select defaultValue="24 months">
              <option>12 months</option>
              <option>24 months</option>
              <option>36 months</option>
              <option>All history</option>
            </select>
          </Field>
          <Field label="On sync failure">
            <select defaultValue="Email + retry">
              <option>Email only</option>
              <option>Email + retry</option>
              <option>Email + retry + Slack</option>
            </select>
          </Field>
        </div>
      </Card>

      <Card title="Exception alerts" subtitle="Notify me when…">
        <div style={{ display: "flex", flexDirection: "column", gap: 1 }}>
          {[
            { l: "Critical exception detected",       v: ["Email", "Slack", "In-app"], on: true },
            { l: "Margin compression > 2 pts",        v: ["Email", "In-app"], on: true },
            { l: "Cash runway falls below threshold", v: ["Email", "Slack"], on: true },
            { l: "AR aging > 90 days appears",        v: ["Email"], on: true },
            { l: "Inventory stockout within 14 days", v: ["Email", "Slack"], on: true },
            { l: "Budget variance > 10%",             v: ["Email"], on: false },
            { l: "Daily digest of all activity",       v: ["Email"], on: false },
          ].map((r, i) => (
            <div key={i} className="pc-alert-row">
              <div style={{ display: "flex", alignItems: "center", gap: 12 }}>
                <Toggle checked={r.on} />
                <span style={{ fontSize: 13 }}>{r.l}</span>
              </div>
              <div style={{ display: "flex", gap: 6 }}>
                {r.v.map(x => <span key={x} className="pc-chip">{x}</span>)}
              </div>
            </div>
          ))}
        </div>
      </Card>
    </>
  );
}

function Toggle({ checked, onChange }) {
  const [on, setOn] = useStateSet(checked);
  return (
    <div className={"pc-toggle " + (on ? "on" : "")} onClick={() => { setOn(v => !v); onChange && onChange(!on); }}>
      <div className="pc-toggle-dot" />
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// PERIOD & CALENDAR
// ────────────────────────────────────────────────────────────────────────
function PeriodPage({ fiscalYear, setFiscalYear, period, setPeriod }) {
  return (
    <div className="pc-page">
      <div className="pc-kpi-grid pc-kpi-grid-4">
        <KPICard label="Current fiscal year" value={fiscalYear} hint="Calendar year ending Dec 31" accent="var(--accent)" />
        <KPICard label="Current period"      value={period} hint="May 1 – May 14, 2026" accent="var(--accent-2)" />
        <KPICard label="Books closed through" value="Apr 2026" hint="Awaiting May close" accent="var(--positive)" />
        <KPICard label="Forecast horizon"    value="12 months" hint="Through May 2027" accent="var(--warning)" />
      </div>

      <Card title="Fiscal calendar" subtitle="Defines how periods, quarters, and years roll up">
        <div className="pc-form-grid">
          <Field label="Fiscal year ends">
            <select defaultValue="December">
              {["December","November","October","September","August","July","June","May","April","March","February","January"].map(m => <option key={m}>{m}</option>)}
            </select>
          </Field>
          <Field label="Current fiscal year">
            <select value={fiscalYear} onChange={(e) => setFiscalYear(e.target.value)}>
              {["FY24","FY25","FY26","FY27 (Plan)"].map(y => <option key={y}>{y}</option>)}
            </select>
          </Field>
          <Field label="Default reporting period">
            <select value={period} onChange={(e) => setPeriod(e.target.value)}>
              {["MTD","QTD","YTD","TTM"].map(p => <option key={p}>{p}</option>)}
            </select>
          </Field>
          <Field label="Period granularity">
            <select defaultValue="Monthly">
              <option>Daily</option><option>Weekly</option><option>Monthly</option><option>4-4-5 retail</option><option>Quarterly</option>
            </select>
          </Field>
          <Field label="Week starts on">
            <select defaultValue="Monday"><option>Sunday</option><option>Monday</option></select>
          </Field>
          <Field label="Business days only">
            <select defaultValue="Yes — exclude weekends + US holidays"><option>Yes — exclude weekends + US holidays</option><option>Yes — weekends only</option><option>No — all days</option></select>
          </Field>
        </div>
      </Card>

      <Card title="Comparison periods" subtitle="What 'prior' means on KPI deltas">
        <div className="pc-form-grid">
          <Field label="Primary comparison">
            <select defaultValue="Prior month"><option>Prior month</option><option>Prior quarter</option><option>Same period last year</option><option>Budget</option><option>Forecast</option></select>
          </Field>
          <Field label="Secondary comparison">
            <select defaultValue="Same period last year"><option>None</option><option>Prior month</option><option>Same period last year</option><option>Budget</option></select>
          </Field>
          <Field label="Variance threshold (yellow)">
            <input type="number" defaultValue={5} />
          </Field>
          <Field label="Variance threshold (red)">
            <input type="number" defaultValue={15} />
          </Field>
        </div>
      </Card>

      <Card title="Close calendar" subtitle="Track period close progress">
        <table className="pc-table compact">
          <thead><tr><th>Period</th><th>Status</th><th>Close target</th><th>Closed on</th><th>Days to close</th></tr></thead>
          <tbody>
            {[
              { p: "May 2026", s: "Open",   t: "Jun 10", c: "—",       d: "—" },
              { p: "Apr 2026", s: "Closed", t: "May 10", c: "May 09",  d: "9d" },
              { p: "Mar 2026", s: "Closed", t: "Apr 10", c: "Apr 11",  d: "11d" },
              { p: "Feb 2026", s: "Closed", t: "Mar 10", c: "Mar 14",  d: "14d" },
              { p: "Jan 2026", s: "Closed", t: "Feb 10", c: "Feb 18",  d: "18d" },
            ].map((r, i) => (
              <tr key={i}>
                <td style={{paddingLeft: 14, fontWeight: 500}}>{r.p}</td>
                <td><StatusPill s={r.s === "Open" ? "Open" : "Paid"} /></td>
                <td style={{fontSize: 11.5, color: "var(--text-3)"}}>{r.t}</td>
                <td style={{fontSize: 11.5, color: "var(--text-3)"}}>{r.c}</td>
                <td style={{fontFamily: "ui-monospace, monospace", color: "var(--text-2)"}}>{r.d}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </Card>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// USERS & ROLES
// ────────────────────────────────────────────────────────────────────────
const ALL_MODULES = [
  { k: "health",        l: "Daily Health View", g: "Today" },
  { k: "weekly",        l: "Weekly Review",     g: "Today" },
  { k: "overview",      l: "Financial Overview", g: "Finance" },
  { k: "cash",          l: "Cash Flow & Runway", g: "Finance" },
  { k: "arap",          l: "AR / AP Aging",     g: "Finance" },
  { k: "expenses",      l: "Expense Intelligence", g: "Finance" },
  { k: "forecast",      l: "Forecast",          g: "Finance" },
  { k: "capital",       l: "Capital Allocation", g: "Finance" },
  { k: "sales",         l: "Sales Analysis",    g: "Revenue" },
  { k: "patterns",      l: "Sales Patterns",    g: "Revenue" },
  { k: "pricing",       l: "Pricing Intelligence", g: "Revenue" },
  { k: "acquisition",   l: "Acquisition & Cohorts", g: "Revenue" },
  { k: "customer",      l: "Customer Profitability", g: "Revenue" },
  { k: "margin",        l: "Margin Analytics",  g: "Revenue" },
  { k: "stores",        l: "Stores",            g: "Operations" },
  { k: "inventory",     l: "Inventory",         g: "Operations" },
  { k: "supply",        l: "Supply Chain",      g: "Operations" },
  { k: "manufacturing", l: "Production & OEE",  g: "Operations" },
  { k: "service",       l: "Resource Productivity", g: "Operations" },
  { k: "exceptions",    l: "Exceptions Inbox",  g: "Insights" },
  { k: "decisions",     l: "Strategic Decisions", g: "Insights" },
  { k: "ratios",        l: "Financial Ratios",  g: "Insights" },
  { k: "goals",         l: "Goals & Targets",   g: "Insights" },
  { k: "risk",          l: "Risk Dashboard",    g: "Insights" },
  { k: "settings_config",  l: "Configuration",   g: "Settings" },
  { k: "settings_period",  l: "Period & Calendar", g: "Settings" },
  { k: "settings_users",   l: "Users & Roles",   g: "Settings" },
  { k: "settings_custom",  l: "Customization",   g: "Settings" },
];

const DEFAULT_ROLE_ACCESS = {
  Owner:   ALL_MODULES.map(m => ({ key: m.k, perm: "E" })),
  Admin:   ALL_MODULES.map(m => ({ key: m.k, perm: m.k === "settings_users" ? "V" : "E" })),
  CFO:     ALL_MODULES.map(m => ({ key: m.k, perm: ["settings_users"].includes(m.k) ? "—" : (m.g === "Settings" ? "V" : "E") })),
  Finance: ALL_MODULES.map(m => ({ key: m.k, perm: ["Finance","Revenue","Insights","Today"].includes(m.g) ? "E" : (m.g === "Settings" ? "—" : "V") })),
  Sales:   ALL_MODULES.map(m => ({ key: m.k, perm: ["Revenue","Today"].includes(m.g) ? "E" : (m.g === "Settings" ? "—" : "V") })),
  Ops:     ALL_MODULES.map(m => ({ key: m.k, perm: ["Operations","Today"].includes(m.g) ? "E" : (m.g === "Settings" ? "—" : "V") })),
  Viewer:  ALL_MODULES.map(m => ({ key: m.k, perm: m.g === "Settings" ? "—" : "V" })),
};

function UsersPage() {
  const [users, setUsers] = useStateSet([]);
  const [editing, setEditing] = useStateSet(null);   // { id?, name, email, role }
  const [confirmDel, setConfirmDel] = useStateSet(null);
  const [search, setSearch] = useStateSet("");
  const [filterRole, setFilterRole] = useStateSet("All");
  const [loadingUsers, setLoadingUsers] = useStateSet(true);

  useEffectSet(() => {
    const db = window.supabaseClient;
    if (!db) { setLoadingUsers(false); return; }
    (async () => {
      const { data: { session } } = await db.auth.getSession();
      if (!session) { setLoadingUsers(false); return; }
      // Find which company this user belongs to
      const { data: membership } = await db
        .from("company_users")
        .select("company_id")
        .eq("user_id", session.user.id)
        .eq("status", "Active")
        .maybeSingle();
      if (!membership) { setLoadingUsers(false); return; }
      // Load all members of this company
      const { data: members } = await db
        .from("company_users")
        .select("id, user_id, role, status, invited_at")
        .eq("company_id", membership.company_id);
      if (!members) { setLoadingUsers(false); return; }
      const mapped = members.map((m, i) => ({
        id: m.id,
        name: m.user_id === session.user.id
          ? (session.user.user_metadata?.full_name || session.user.email?.split("@")[0] || "You")
          : m.user_id.slice(0, 8),
        email: m.user_id === session.user.id ? session.user.email : "—",
        role: m.role || "Viewer",
        status: m.status || "Active",
        mfa: false,
        joined: m.invited_at ? new Date(m.invited_at).toLocaleDateString("en-US", { month: "short", year: "numeric" }) : "—",
        last: m.user_id === session.user.id ? "Now" : "—",
      }));
      setUsers(mapped);
      setLoadingUsers(false);
    })();
  }, []);

  const active = users.filter(u => u.status === "Active").length;
  const pending = users.filter(u => u.status === "Pending").length;
  const mfaCount = users.filter(u => u.mfa && u.status === "Active").length;

  const filtered = users.filter(u => {
    if (filterRole !== "All" && u.role !== filterRole) return false;
    if (search && !(u.name.toLowerCase().includes(search.toLowerCase()) || u.email.toLowerCase().includes(search.toLowerCase()))) return false;
    return true;
  });

  const saveUser = (u) => {
    if (u.id) {
      setUsers(list => list.map(x => x.id === u.id ? { ...x, ...u } : x));
    } else {
      const id = Math.max(0, ...users.map(x => x.id)) + 1;
      setUsers(list => [...list, { id, name: u.name, email: u.email, role: u.role, status: "Pending", mfa: false, last: "Never", joined: "Just now" }]);
    }
    setEditing(null);
  };
  const deleteUser = (id) => {
    setUsers(list => list.filter(x => x.id !== id));
    setConfirmDel(null);
  };
  const resendInvite = (u) => { alert("Invitation resent to " + u.email); };
  const toggleMFA = (id) => setUsers(list => list.map(x => x.id === id ? { ...x, mfa: !x.mfa } : x));
  const suspendUser = (id) => setUsers(list => list.map(x => x.id === id ? { ...x, status: x.status === "Suspended" ? "Active" : "Suspended" } : x));

  return (
    <div className="pc-page">
      <div className="pc-kpi-grid pc-kpi-grid-4">
        <KPICard label="Active seats"     value={active + " / 10"} hint="Pro plan — $49/user/mo" accent="var(--accent)" />
        <KPICard label="Pending invites"  value={pending}      hint={pending > 0 ? users.filter(u => u.status === "Pending").map(u => u.name).join(", ") : "None"} accent="var(--warning)" />
        <KPICard label="MFA adoption"     value={active > 0 ? Math.round(mfaCount/active*100) + "%" : "—"}    hint={mfaCount + " of " + active + " active users"} accent="var(--accent-2)" />
        <KPICard label="Audit log retention" value="2 years" hint="Pro plan default" accent="var(--positive)" />
      </div>

      <Card title="Team" subtitle="Manage who has access · what they can see · what they can do"
            action={
              <div style={{ display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap" }}>
                <input className="pc-period-select" style={{ minWidth: 180 }} placeholder="Search by name or email" value={search} onChange={(e) => setSearch(e.target.value)} />
                <select className="pc-period-select" value={filterRole} onChange={(e) => setFilterRole(e.target.value)}>
                  <option>All</option>
                  {Object.keys(DEFAULT_ROLE_ACCESS).map(r => <option key={r}>{r}</option>)}
                </select>
                <ExportButton rows={users.map(u => ({ Name: u.name, Email: u.email, Role: u.role, Status: u.status, MFA: u.mfa ? "Yes" : "No", LastSeen: u.last, Joined: u.joined }))} filename="users" />
                <button className="pc-btn-mini" onClick={() => setEditing({ name: "", email: "", role: "Viewer" })}>+ Invite user</button>
              </div>
            } padding={0}>
        <table className="pc-table">
          <thead><tr><th>Name</th><th>Email</th><th>Role</th><th>Last seen</th><th>MFA</th><th>Status</th><th>Joined</th><th style={{textAlign: "right", paddingRight: 14}}>Actions</th></tr></thead>
          <tbody>
            {filtered.map((u) => (
              <tr key={u.id} style={{ opacity: u.status === "Suspended" ? 0.55 : 1 }}>
                <td style={{paddingLeft: 14}}>
                  <div style={{ display: "flex", alignItems: "center", gap: 10 }}>
                    <div style={{ width: 28, height: 28, borderRadius: "50%", background: "linear-gradient(135deg, #8b5cf6, #ec4899)", display: "flex", alignItems: "center", justifyContent: "center", fontSize: 11, fontWeight: 600, color: "white" }}>
                      {u.name.split(" ").map(w => w[0]).join("").slice(0, 2)}
                    </div>
                    <span style={{ fontWeight: 500 }}>{u.name}</span>
                  </div>
                </td>
                <td style={{fontSize: 12, color: "var(--text-2)"}}>{u.email}</td>
                <td><span className="pc-chip">{u.role}</span></td>
                <td style={{fontSize: 11.5, color: "var(--text-3)"}}>{u.last}</td>
                <td>{u.mfa ? <Icon d={icons.check} size={14} stroke="var(--positive)" strokeWidth={2.4} /> : <span style={{fontSize: 11, color: "var(--warning)"}}>Off</span>}</td>
                <td>
                  <span className="pc-statpill" style={{
                    background: u.status === "Active" ? "rgba(110,231,183,0.12)" : u.status === "Pending" ? "rgba(251,191,36,0.12)" : "rgba(148,163,184,0.15)",
                    color: u.status === "Active" ? "var(--positive)" : u.status === "Pending" ? "var(--warning)" : "var(--text-3)",
                  }}>{u.status}</span>
                </td>
                <td style={{fontSize: 11.5, color: "var(--text-3)"}}>{u.joined}</td>
                <td style={{ paddingRight: 14, textAlign: "right" }}>
                  <div style={{ display: "inline-flex", gap: 4 }}>
                    <button className="pc-btn-mini ghost" onClick={() => setEditing(u)}>Edit</button>
                    {u.status === "Pending" && <button className="pc-btn-mini ghost" onClick={() => resendInvite(u)}>Resend</button>}
                    {u.status !== "Pending" && (
                      <button className="pc-btn-mini ghost" onClick={() => suspendUser(u.id)}>{u.status === "Suspended" ? "Reactivate" : "Suspend"}</button>
                    )}
                    {u.role !== "Owner" && <button className="pc-btn-mini ghost" style={{ color: "var(--danger)" }} onClick={() => setConfirmDel(u)}>Delete</button>}
                  </div>
                </td>
              </tr>
            ))}
            {filtered.length === 0 && (
              <tr><td colSpan={8} style={{padding: 28, textAlign: "center", color: "var(--text-3)", fontSize: 13}}>No users match this filter.</td></tr>
            )}
          </tbody>
        </table>
      </Card>

      <Card title="Roles & permissions" subtitle="What each role can see and do · click a role to view its full access map">
        <div style={{ overflowX: "auto" }}>
          <table className="pc-table compact">
            <thead>
              <tr>
                <th>Module</th>
                {Object.keys(DEFAULT_ROLE_ACCESS).map(r => <th key={r} style={{ textAlign: "center" }}>{r}</th>)}
              </tr>
            </thead>
            <tbody>
              {ALL_MODULES.map((m, i) => (
                <tr key={i}>
                  <td style={{paddingLeft: 14, fontWeight: 500}}>{m.l} <span style={{ color: "var(--text-3)", fontSize: 11 }}>· {m.g}</span></td>
                  {Object.keys(DEFAULT_ROLE_ACCESS).map(r => {
                    const access = DEFAULT_ROLE_ACCESS[r].find(a => a.key === m.k);
                    return <td key={r} style={{ textAlign: "center" }}><PermPill p={access ? access.perm : "—"} /></td>;
                  })}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div style={{ display: "flex", gap: 18, marginTop: 14, fontSize: 11, color: "var(--text-3)" }}>
          <span><PermPill p="E" /> &nbsp;Edit · full access</span>
          <span><PermPill p="V" /> &nbsp;View only</span>
          <span><PermPill p="—" /> &nbsp;No access</span>
        </div>
      </Card>

      <Card title="Activity log" subtitle="Recent significant actions">
        <div style={{ fontSize: 12.5, color: "var(--text-3)", padding: "8px 0" }}>
          Activity logging will appear here as your team uses the platform.
        </div>
      </Card>

      {editing && <UserEditorModal user={editing} onClose={() => setEditing(null)} onSave={saveUser} />}
      {confirmDel && <ConfirmDeleteModal user={confirmDel} onClose={() => setConfirmDel(null)} onConfirm={() => deleteUser(confirmDel.id)} />}
    </div>
  );
}

function UserEditorModal({ user, onClose, onSave }) {
  const [name, setName] = useStateSet(user.name || "");
  const [email, setEmail] = useStateSet(user.email || "");
  const [role, setRole] = useStateSet(user.role || "Viewer");
  const access = DEFAULT_ROLE_ACCESS[role] || [];
  const grouped = ALL_MODULES.reduce((acc, m) => {
    if (!acc[m.g]) acc[m.g] = [];
    acc[m.g].push(m);
    return acc;
  }, {});

  const canSave = name.trim() && /^[^@\s]+@[^@\s]+\.[^@\s]+$/.test(email);

  return (
    <div className="pc-modal-backdrop" onClick={onClose}>
      <div className="pc-modal pc-modal-wide" onClick={(e) => e.stopPropagation()}>
        <div className="pc-modal-hd">
          <div>
            <div style={{ fontSize: 11, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5 }}>{user.id ? "Edit user" : "Invite a new user"}</div>
            <div style={{ fontSize: 18, fontWeight: 600 }}>{user.id ? user.name : "Add team member"}</div>
          </div>
          <button className="pc-icon-btn" onClick={onClose} title="Close"><Icon d={icons.x} size={14} /></button>
        </div>
        <div className="pc-modal-body">
          <div className="pc-form-grid">
            <Field label="Full name">
              <input value={name} onChange={(e) => setName(e.target.value)} placeholder="Full name" />
            </Field>
            <Field label="Email address">
              <input type="email" value={email} onChange={(e) => setEmail(e.target.value)} placeholder="name@company.com" />
            </Field>
            <Field label="Role">
              <select value={role} onChange={(e) => setRole(e.target.value)}>
                {Object.keys(DEFAULT_ROLE_ACCESS).map(r => <option key={r}>{r}</option>)}
              </select>
            </Field>
            <Field label="Send invitation by">
              <select defaultValue="Email">
                <option>Email</option>
                <option>Email + Slack</option>
                <option>Direct link (manual share)</option>
              </select>
            </Field>
          </div>

          <div style={{ marginTop: 22 }}>
            <div className="pc-drill-section-label">Portal access this role grants</div>
            <div style={{ display: "grid", gridTemplateColumns: "repeat(2, 1fr)", gap: 16 }}>
              {Object.entries(grouped).map(([g, mods]) => (
                <div key={g}>
                  <div style={{ fontSize: 10.5, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5, marginBottom: 6 }}>{g}</div>
                  <div style={{ display: "flex", flexDirection: "column", gap: 4 }}>
                    {mods.map(m => {
                      const a = access.find(x => x.key === m.k);
                      return (
                        <div key={m.k} style={{ display: "flex", alignItems: "center", justifyContent: "space-between", padding: "4px 0", fontSize: 12, borderBottom: "1px solid var(--border)" }}>
                          <span>{m.l}</span>
                          <PermPill p={a ? a.perm : "—"} />
                        </div>
                      );
                    })}
                  </div>
                </div>
              ))}
            </div>
            <div style={{ marginTop: 14, fontSize: 12, color: "var(--text-3)" }}>
              Want more granular access? Define a custom role in <b>Settings → Roles</b> (coming soon).
            </div>
          </div>
        </div>
        <div style={{ padding: "14px 18px", borderTop: "1px solid var(--border)", display: "flex", justifyContent: "flex-end", gap: 8 }}>
          <button className="pc-btn ghost" onClick={onClose}>Cancel</button>
          <button className="pc-btn primary" disabled={!canSave} onClick={() => onSave({ ...user, name, email, role })}>
            {user.id ? "Save changes" : "Send invitation"}
          </button>
        </div>
      </div>
    </div>
  );
}

function ConfirmDeleteModal({ user, onClose, onConfirm }) {
  return (
    <div className="pc-modal-backdrop" onClick={onClose}>
      <div className="pc-modal" style={{ maxWidth: 480 }} onClick={(e) => e.stopPropagation()}>
        <div className="pc-modal-hd">
          <div style={{ fontSize: 14, fontWeight: 600 }}>Delete user?</div>
          <button className="pc-icon-btn" onClick={onClose}><Icon d={icons.x} size={14} /></button>
        </div>
        <div className="pc-modal-body">
          <div style={{ fontSize: 13, lineHeight: 1.6 }}>
            Are you sure you want to delete <b>{user.name}</b> ({user.email})? They'll lose access immediately.
            Audit history of their actions will be preserved.
          </div>
        </div>
        <div style={{ padding: "14px 18px", borderTop: "1px solid var(--border)", display: "flex", justifyContent: "flex-end", gap: 8 }}>
          <button className="pc-btn ghost" onClick={onClose}>Cancel</button>
          <button className="pc-btn" style={{ background: "var(--danger)", color: "white", borderColor: "var(--danger)" }} onClick={onConfirm}>Delete user</button>
        </div>
      </div>
    </div>
  );
}

function PermPill({ p }) {
  if (p === "E") return <span className="pc-perm-pill" style={{ background: "rgba(5,150,105,0.15)", color: "var(--positive)" }}>E</span>;
  if (p === "V") return <span className="pc-perm-pill" style={{ background: "rgba(99,102,241,0.15)", color: "var(--accent-2)" }}>V</span>;
  return <span className="pc-perm-pill" style={{ background: "var(--bg-elev-1)", color: "var(--text-3)" }}>—</span>;
}

// ────────────────────────────────────────────────────────────────────────
// CUSTOMIZATION — replaces the floating Tweaks panel
// ────────────────────────────────────────────────────────────────────────
function CustomizePage({ t, setTweak, onRerunWizard }) {
  const accents = ["#6ee7b7", "#60a5fa", "#fbbf24", "#a78bfa", "#f472b6"];
  return (
    <div className="pc-page">
      <Card title="Appearance" subtitle="How Perdura looks for you">
        <div className="pc-form-grid">
          <Field label="Theme">
            <div className="pc-radio-row">
              {[
                { v: false, l: "Light", desc: "Easier on the eyes for long sessions" },
                { v: true,  l: "Dark",  desc: "Premium · high contrast" },
              ].map(o => (
                <button key={o.l} className={"pc-theme-card " + (t.dark === o.v ? "selected" : "")} onClick={() => setTweak("dark", o.v)}>
                  <div className="pc-theme-preview" data-mode={o.v ? "dark" : "light"}>
                    <div className="pc-theme-sb" />
                    <div className="pc-theme-main">
                      <div className="pc-theme-bar" />
                      <div className="pc-theme-cards">
                        <div /><div /><div />
                      </div>
                    </div>
                  </div>
                  <div style={{ marginTop: 8 }}>
                    <div style={{ fontSize: 13, fontWeight: 600 }}>{o.l}</div>
                    <div style={{ fontSize: 11.5, color: "var(--text-3)" }}>{o.desc}</div>
                  </div>
                </button>
              ))}
            </div>
          </Field>
          <Field label="Density">
            <div className="pc-radio-row">
              {[
                { v: "compact", l: "Compact" },
                { v: "regular", l: "Regular" },
                { v: "comfy",   l: "Comfy" },
              ].map(o => (
                <button key={o.v} className={"pc-density-btn " + (t.density === o.v ? "selected" : "")} onClick={() => setTweak("density", o.v)}>
                  {o.l}
                </button>
              ))}
            </div>
          </Field>
          <Field label="Accent color">
            <div className="pc-accent-row">
              {accents.map(a => (
                <button key={a} className={"pc-accent-swatch " + (t.accent === a ? "selected" : "")}
                  style={{ background: a }}
                  onClick={() => setTweak("accent", a)}
                  aria-label={"Accent " + a} />
              ))}
            </div>
          </Field>
          <Field label="Default persona view">
            <select value={t.persona} onChange={(e) => setTweak("persona", e.target.value)}>
              <option>CEO</option><option>CFO</option><option>Ops</option>
            </select>
          </Field>
        </div>
      </Card>

      <Card title="Plain-English mode" subtitle="Swap finance jargon for everyday language across the app">
        <div style={{ display: "flex", alignItems: "center", justifyContent: "space-between", gap: 16, flexWrap: "wrap" }}>
          <div style={{ flex: 1, minWidth: 280 }}>
            <div style={{ display: "flex", alignItems: "center", gap: 12, marginBottom: 10 }}>
              <Toggle checked={t.plainEnglish} onChange={(v) => setTweak("plainEnglish", v)} />
              <div style={{ fontSize: 13, fontWeight: 500 }}>{t.plainEnglish ? "On — using plain language" : "Off — using finance terms"}</div>
            </div>
            <div style={{ fontSize: 12.5, color: "var(--text-2)", lineHeight: 1.55 }}>
              Replaces dense terms with what they actually mean. For owners who didn't go to business school.
            </div>
          </div>
          <div style={{ background: "var(--bg-elev-1)", border: "1px solid var(--border)", borderRadius: "var(--r)", padding: 14, minWidth: 280, flex: 1 }}>
            <div style={{ fontSize: 10.5, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5, marginBottom: 8 }}>Examples</div>
            <div style={{ display: "grid", gridTemplateColumns: "1fr auto 1fr", gap: 8, fontSize: 12, alignItems: "center" }}>
              <div style={{ color: "var(--text-3)" }}>EBITDA</div>
              <div style={{ color: "var(--text-4)" }}>→</div>
              <div style={{ color: "var(--text)" }}>Operating profit</div>
              <div style={{ color: "var(--text-3)" }}>DSO</div>
              <div style={{ color: "var(--text-4)" }}>→</div>
              <div style={{ color: "var(--text)" }}>Days customers take to pay</div>
              <div style={{ color: "var(--text-3)" }}>Cash on hand</div>
              <div style={{ color: "var(--text-4)" }}>→</div>
              <div style={{ color: "var(--text)" }}>Money in your bank</div>
              <div style={{ color: "var(--text-3)" }}>Gross margin %</div>
              <div style={{ color: "var(--text-4)" }}>→</div>
              <div style={{ color: "var(--text)" }}>Profit per dollar sold</div>
            </div>
          </div>
        </div>
      </Card>

      <Card title="Business profile" subtitle="Drives which dashboards and KPIs you see">
        <div className="pc-form-grid">
          <Field label="Business type">
            <select value={t.bizType} onChange={(e) => setTweak("bizType", e.target.value)}>
              <option value="service">Service business</option>
              <option value="product">Product / e-commerce</option>
              <option value="retail">Retail with stores</option>
              <option value="manufacturing">Manufacturing</option>
            </select>
          </Field>
          <Field label="Default landing page">
            <select defaultValue="Financial Overview">
              <option>Financial Overview</option>
              <option>Sales Analysis</option>
              <option>Cash Flow & Runway</option>
              <option>Exceptions Inbox</option>
              <option>Last visited</option>
            </select>
          </Field>
        </div>
      </Card>

      <Card title="Notifications" subtitle="Frequency of routine summaries">
        <div className="pc-form-grid">
          <Field label="Daily digest">
            <select defaultValue="Off"><option>Off</option><option>Email · 7am</option><option>Email · 5pm</option><option>Slack · 7am</option></select>
          </Field>
          <Field label="Weekly business review">
            <select defaultValue="Monday 6am"><option>Off</option><option>Monday 6am</option><option>Friday 4pm</option><option>Sunday 6pm</option></select>
          </Field>
          <Field label="Monthly close summary">
            <select defaultValue="On"><option>Off</option><option>On</option></select>
          </Field>
        </div>
      </Card>

      <Card title="Advanced" subtitle="Demo & development controls">
        <div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
          <button className="pc-btn ghost" onClick={onRerunWizard}>Re-run setup wizard</button>
          <button className="pc-btn ghost">Reset all customizations</button>
          <button className="pc-btn ghost">Generate sample data</button>
        </div>
      </Card>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// CONTACT US
// ────────────────────────────────────────────────────────────────────────
function ContactPage({ companyProfile }) {
  const [settings, setSettings] = useStateSet(null);
  const [form, setForm] = useStateSet({ name: "", email: "", subject: "General inquiry", message: "" });
  const [status, setStatus] = useStateSet("idle"); // idle | sending | sent | error
  const [userEmail, setUserEmail] = useStateSet("");
  const [userName, setUserName] = useStateSet("");

  useEffectSet(() => {
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      const [{ data: s }, { data: { session } }] = await Promise.all([
        db.from("platform_settings").select("key,value").in("key", [
          "support_email", "contact_email", "billing_email",
          "support_phone", "support_hours", "brand_name",
          "company_name", "calendly_url",
        ]),
        db.auth.getSession(),
      ]);
      const map = {};
      (s || []).forEach(r => { map[r.key] = r.value; });
      setSettings(map);
      if (session?.user) {
        const name = session.user.user_metadata?.full_name || session.user.email?.split("@")[0] || "";
        setUserEmail(session.user.email || "");
        setUserName(name);
        setForm(prev => ({ ...prev, name, email: session.user.email || "" }));
      }
    })();
  }, []);

  const supportEmail = settings?.support_email || "craig@perduracapital.com";
  const contactEmail = settings?.contact_email || supportEmail;
  const billingEmail = settings?.billing_email || supportEmail;
  const phone       = settings?.support_phone || "";
  const hours       = settings?.support_hours || "Mon – Fri, 9am – 6pm ET";
  const brandName   = settings?.brand_name || "PerduraCFO";
  const calendlyUrl = settings?.calendly_url || "";

  const SUBJECTS = [
    "General inquiry",
    "Technical support",
    "Billing & payments",
    "Feature request",
    "Integration help",
    "Account access",
    "Other",
  ];

  const handleSubmit = async (e) => {
    e.preventDefault();
    if (!form.name.trim() || !form.email.trim() || !form.message.trim()) return;
    setStatus("sending");
    // Compose mailto link as fallback — a real email send would go through an edge function
    const to = form.subject === "Billing & payments" ? billingEmail : supportEmail;
    const body = `From: ${form.name} (${form.email})\nCompany: ${companyProfile?.name || "—"}\nSubject: ${form.subject}\n\n${form.message}`;
    // Try to open mail client; also mark as "sent" optimistically
    setTimeout(() => {
      window.open(`mailto:${to}?subject=${encodeURIComponent(`[${brandName}] ${form.subject}`)}&body=${encodeURIComponent(body)}`);
      setStatus("sent");
    }, 600);
  };

  const CONTACT_CHANNELS = [
    {
      icon: (
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"/><polyline points="22,6 12,13 2,6"/>
        </svg>
      ),
      label: "Support",
      value: supportEmail,
      sub: "Fastest response",
      href: `mailto:${supportEmail}`,
      accent: "var(--accent)",
    },
    {
      icon: (
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <rect x="1" y="4" width="22" height="16" rx="2"/><line x1="1" y1="10" x2="23" y2="10"/>
        </svg>
      ),
      label: "Billing",
      value: billingEmail,
      sub: "Invoices & payments",
      href: `mailto:${billingEmail}`,
      accent: "#3b82f6",
    },
    ...(phone ? [{
      icon: (
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <path d="M22 16.92v3a2 2 0 0 1-2.18 2 19.79 19.79 0 0 1-8.63-3.07A19.5 19.5 0 0 1 4.69 13a19.79 19.79 0 0 1-3.07-8.67A2 2 0 0 1 3.6 2h3a2 2 0 0 1 2 1.72c.127.96.361 1.903.7 2.81a2 2 0 0 1-.45 2.11L7.91 9.91a16 16 0 0 0 6.18 6.18l1.97-1.97a2 2 0 0 1 2.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0 1 22 16.92z"/>
        </svg>
      ),
      label: "Phone",
      value: phone,
      sub: hours,
      href: `tel:${phone.replace(/\s/g, "")}`,
      accent: "#10b981",
    }] : []),
    ...(calendlyUrl ? [{
      icon: (
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round">
          <rect x="3" y="4" width="18" height="18" rx="2" ry="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/>
        </svg>
      ),
      label: "Book a call",
      value: "Schedule 30 min",
      sub: "Onboarding & strategy",
      href: calendlyUrl,
      accent: "#d97706",
    }] : []),
  ];

  return (
    <div className="pc-page">
      {/* Header */}
      <div style={{ marginBottom: 28 }}>
        <div style={{ fontSize: 11, fontWeight: 600, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.6, marginBottom: 6 }}>Support</div>
        <div style={{ fontSize: 24, fontWeight: 700, letterSpacing: -0.04, marginBottom: 8, color: "var(--text)" }}>Contact us</div>
        <div style={{ fontSize: 14, color: "var(--text-2)", lineHeight: 1.6, maxWidth: 540 }}>
          Our team is here to help. Send a message below or reach us directly — we typically respond within one business day.
        </div>
      </div>

      <div style={{ display: "grid", gridTemplateColumns: "1fr 380px", gap: 24, alignItems: "start" }}>

        {/* Left: contact form */}
        <div>
          {status === "sent" ? (
            <Card>
              <div style={{ padding: "40px 24px", textAlign: "center" }}>
                <div style={{
                  width: 60, height: 60, borderRadius: "50%",
                  background: "rgba(16,185,129,0.1)", border: "1.5px solid rgba(16,185,129,0.3)",
                  display: "flex", alignItems: "center", justifyContent: "center",
                  margin: "0 auto 18px",
                }}>
                  <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="#10b981" strokeWidth="2.4" strokeLinecap="round" strokeLinejoin="round"><polyline points="20 6 9 17 4 12"/></svg>
                </div>
                <div style={{ fontSize: 17, fontWeight: 700, marginBottom: 8, letterSpacing: -0.02 }}>Message sent</div>
                <div style={{ fontSize: 13, color: "var(--text-2)", lineHeight: 1.6, marginBottom: 24, maxWidth: 360, margin: "0 auto 24px" }}>
                  Your message has been opened in your email client. Our team will get back to you at <strong>{form.email}</strong>.
                </div>
                <button
                  className="pc-btn-mini ghost"
                  onClick={() => { setStatus("idle"); setForm(prev => ({ ...prev, subject: "General inquiry", message: "" })); }}
                >Send another message</button>
              </div>
            </Card>
          ) : (
            <Card title="Send us a message" subtitle={`We'll reply to ${form.email || "your email address"}`}>
              <form onSubmit={handleSubmit}>
                <div className="pc-form-grid">
                  <Field label="Your name">
                    <input
                      className="pc-period-select"
                      style={{ fontSize: 13, padding: "9px 10px" }}
                      value={form.name}
                      onChange={e => setForm(p => ({ ...p, name: e.target.value }))}
                      placeholder="Your name"
                      required
                    />
                  </Field>
                  <Field label="Email address">
                    <input
                      type="email"
                      className="pc-period-select"
                      style={{ fontSize: 13, padding: "9px 10px" }}
                      value={form.email}
                      onChange={e => setForm(p => ({ ...p, email: e.target.value }))}
                      placeholder="you@company.com"
                      required
                    />
                  </Field>
                </div>

                <Field label="Subject">
                  <select
                    className="pc-period-select"
                    style={{ fontSize: 13, padding: "9px 10px", width: "100%" }}
                    value={form.subject}
                    onChange={e => setForm(p => ({ ...p, subject: e.target.value }))}
                  >
                    {SUBJECTS.map(s => <option key={s}>{s}</option>)}
                  </select>
                </Field>

                <Field label="Message">
                  <textarea
                    className="pc-period-select"
                    style={{ width: "100%", minHeight: 140, resize: "vertical", fontSize: 13, padding: "9px 10px", fontFamily: "inherit", lineHeight: 1.6, boxSizing: "border-box" }}
                    value={form.message}
                    onChange={e => setForm(p => ({ ...p, message: e.target.value }))}
                    placeholder="Describe your question or issue in as much detail as you can…"
                    required
                  />
                </Field>

                <div style={{ display: "flex", alignItems: "center", gap: 12, marginTop: 4 }}>
                  <button
                    type="submit"
                    className="pc-btn primary"
                    style={{ padding: "11px 28px" }}
                    disabled={status === "sending" || !form.name.trim() || !form.message.trim()}
                  >
                    {status === "sending" ? "Opening email…" : "Send message →"}
                  </button>
                  <div style={{ fontSize: 11.5, color: "var(--text-3)", lineHeight: 1.5 }}>
                    This will open your email client pre-filled and ready to send.
                  </div>
                </div>
              </form>
            </Card>
          )}
        </div>

        {/* Right: contact channels + info */}
        <div style={{ display: "flex", flexDirection: "column", gap: 16 }}>

          {/* Contact channels */}
          <Card title="Get in touch">
            <div style={{ display: "flex", flexDirection: "column", gap: 1 }}>
              {CONTACT_CHANNELS.map((ch, i) => (
                <a
                  key={i}
                  href={ch.href}
                  target={ch.href.startsWith("http") ? "_blank" : undefined}
                  rel="noopener noreferrer"
                  style={{
                    display: "flex", alignItems: "center", gap: 13,
                    padding: "13px 16px", borderRadius: 8, textDecoration: "none",
                    transition: "background 0.1s", color: "inherit",
                  }}
                  onMouseEnter={e => e.currentTarget.style.background = "var(--bg-elev-2)"}
                  onMouseLeave={e => e.currentTarget.style.background = "transparent"}
                >
                  <div style={{
                    width: 38, height: 38, borderRadius: 10, flexShrink: 0,
                    background: `${ch.accent}18`, border: `1px solid ${ch.accent}30`,
                    display: "flex", alignItems: "center", justifyContent: "center",
                    color: ch.accent,
                  }}>
                    {ch.icon}
                  </div>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: 11, fontWeight: 600, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.4, marginBottom: 2 }}>{ch.label}</div>
                    <div style={{ fontSize: 13, fontWeight: 600, color: "var(--text)", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{ch.value}</div>
                    <div style={{ fontSize: 11, color: "var(--text-3)", marginTop: 1 }}>{ch.sub}</div>
                  </div>
                  <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="var(--text-4)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><polyline points="9 18 15 12 9 6"/></svg>
                </a>
              ))}
            </div>
          </Card>

          {/* Response time / SLA card */}
          <Card>
            <div style={{ padding: "4px 0" }}>
              <div style={{ fontSize: 11, fontWeight: 600, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5, marginBottom: 12 }}>Response times</div>
              {[
                { label: "General support",     time: "Within 24 hours", dot: "var(--accent)" },
                { label: "Billing questions",   time: "Within 4 hours",  dot: "#3b82f6" },
                { label: "Critical issues",     time: "Within 2 hours",  dot: "#ef4444" },
              ].map((row, i) => (
                <div key={i} style={{ display: "flex", justifyContent: "space-between", alignItems: "center", padding: "8px 0", borderBottom: i < 2 ? "1px solid var(--border)" : "none" }}>
                  <div style={{ display: "flex", alignItems: "center", gap: 8 }}>
                    <div style={{ width: 7, height: 7, borderRadius: "50%", background: row.dot, flexShrink: 0 }} />
                    <span style={{ fontSize: 12.5, color: "var(--text-2)" }}>{row.label}</span>
                  </div>
                  <span style={{ fontSize: 12, fontWeight: 600, color: "var(--text-3)" }}>{row.time}</span>
                </div>
              ))}
              <div style={{ marginTop: 12, fontSize: 11.5, color: "var(--text-3)", lineHeight: 1.55 }}>
                {hours}
              </div>
            </div>
          </Card>

          {/* Company info */}
          <Card>
            <div style={{ fontSize: 11, fontWeight: 600, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: 0.5, marginBottom: 10 }}>About {brandName}</div>
            <div style={{ fontSize: 12.5, color: "var(--text-2)", lineHeight: 1.65 }}>
              {brandName} is a financial intelligence platform for small and mid-sized businesses. We're here to make your numbers clear, actionable, and always available.
            </div>
            <div style={{ marginTop: 12, fontSize: 11.5, color: "var(--text-3)" }}>
              Operated by {settings?.company_name || "Perdura Capital LLC"}
            </div>
          </Card>
        </div>
      </div>
    </div>
  );
}

// ────────────────────────────────────────────────────────────────────────
// DOCUMENTS — customer-facing document portal
// ────────────────────────────────────────────────────────────────────────
function DocumentsPage({ companyProfile, scopedCompanyId }) {
  const [docs, setDocs] = useStateSet([]);
  const [loading, setLoading] = useStateSet(true);
  const [previewDoc, setPreviewDoc] = useStateSet(null);
  const [acknowledging, setAcknowledging] = useStateSet(false);
  const [companyId, setCompanyId] = useStateSet(scopedCompanyId || companyProfile?.id || null);

  useEffectSet(() => {
    if (companyId) return;
    const db = window.supabaseClient;
    if (!db) return;
    (async () => {
      const { data: { session } } = await db.auth.getSession();
      if (!session) return;
      const { data: m } = await db.from("company_users").select("company_id").eq("user_id", session.user.id).eq("status", "Active").maybeSingle();
      if (m?.company_id) setCompanyId(m.company_id);
    })();
  }, []);

  useEffectSet(() => {
    if (!companyId) return;
    const db = window.supabaseClient;
    (async () => {
      setLoading(true);
      const { data } = await db.from("company_documents")
        .select("*")
        .eq("company_id", companyId)
        .in("status", ["published", "signed"])
        .order("created_at", { ascending: false });
      setDocs(data || []);
      setLoading(false);
    })();
  }, [companyId]);

  async function acknowledge(doc) {
    setAcknowledging(true);
    const db = window.supabaseClient;
    const { data: { session } } = await db.auth.getSession();
    await db.from("company_documents").update({
      status: "signed",
      signed_at: new Date().toISOString(),
      signed_by_user_id: session?.user?.id,
      updated_at: new Date().toISOString(),
    }).eq("id", doc.id);
    setDocs(prev => prev.map(d => d.id === doc.id ? { ...d, status: "signed", signed_at: new Date().toISOString() } : d));
    setPreviewDoc(prev => prev ? { ...prev, status: "signed", signed_at: new Date().toISOString() } : null);
    setAcknowledging(false);
  }

  const catColors = { contract: "#3b82f6", manual: "#10b981", policy: "#d97706", guide: "#8b5cf6", onboarding: "#059669" };
  const catColor = (cat) => catColors[cat] || "#94a3b8";

  const contracts = docs.filter(d => d.category === "contract");
  const manuals   = docs.filter(d => d.category === "manual");
  const policies  = docs.filter(d => d.category === "policy");
  const guides    = docs.filter(d => ["guide", "onboarding"].includes(d.category));

  function DocCard({ doc }) {
    const isContract = doc.category === "contract";
    const isSigned = doc.status === "signed";
    return (
      <div style={{
        background: "var(--bg-elev-1)", border: "1px solid var(--border)",
        borderRadius: 10, padding: "16px 18px", display: "flex", gap: 14, alignItems: "flex-start",
        transition: "border-color 0.15s, box-shadow 0.15s",
      }}
        onMouseEnter={e => { e.currentTarget.style.borderColor = "var(--border-strong)"; e.currentTarget.style.boxShadow = "0 2px 12px rgba(0,0,0,0.08)"; }}
        onMouseLeave={e => { e.currentTarget.style.borderColor = "var(--border)"; e.currentTarget.style.boxShadow = "none"; }}
      >
        <div style={{
          width: 40, height: 40, borderRadius: 8, flexShrink: 0,
          background: `${catColor(doc.category)}18`,
          display: "flex", alignItems: "center", justifyContent: "center",
        }}>
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke={catColor(doc.category)} strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
            <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>
          </svg>
        </div>
        <div style={{ flex: 1, minWidth: 0 }}>
          <div style={{ fontWeight: 600, fontSize: 14, color: "var(--text)", marginBottom: 4 }}>{doc.name}</div>
          <div style={{ display: "flex", alignItems: "center", gap: 10, flexWrap: "wrap" }}>
            <span style={{ fontSize: 11.5, color: catColor(doc.category), textTransform: "capitalize", fontWeight: 500 }}>{doc.category}</span>
            <span style={{ fontSize: 11.5, color: "var(--text-3)" }}>v{doc.version}</span>
            {isSigned && (
              <span style={{ fontSize: 11, padding: "2px 8px", borderRadius: 99, background: "rgba(59,130,246,0.12)", color: "#3b82f6", fontWeight: 500 }}>
                Acknowledged {doc.signed_at ? new Date(doc.signed_at).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" }) : ""}
              </span>
            )}
            {isContract && !isSigned && (
              <span style={{ fontSize: 11, padding: "2px 8px", borderRadius: 99, background: "rgba(217,119,6,0.12)", color: "#d97706", fontWeight: 500 }}>
                Requires acknowledgement
              </span>
            )}
          </div>
        </div>
        <button
          onClick={() => setPreviewDoc(doc)}
          style={{ flexShrink: 0, background: "none", border: "1px solid var(--border)", borderRadius: 6, padding: "6px 14px", fontSize: 12.5, color: "var(--text-2)", cursor: "pointer", whiteSpace: "nowrap" }}
        >
          View document
        </button>
      </div>
    );
  }

  function DocGroup({ title, items }) {
    if (!items.length) return null;
    return (
      <div style={{ marginBottom: 28 }}>
        <div style={{ fontSize: 11, fontWeight: 700, color: "var(--text-3)", textTransform: "uppercase", letterSpacing: "0.08em", marginBottom: 10 }}>{title}</div>
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          {items.map(d => <DocCard key={d.id} doc={d} />)}
        </div>
      </div>
    );
  }

  return (
    <div className="pc-page">
      <div className="pc-page-header" style={{ marginBottom: 24 }}>
        <h1 className="pc-page-title">Documents</h1>
        <p style={{ fontSize: 13.5, color: "var(--text-3)", margin: "4px 0 0" }}>Your agreements, manuals, and platform guides.</p>
      </div>

      {loading ? (
        <div style={{ textAlign: "center", padding: 60, color: "var(--text-3)", fontSize: 13 }}>Loading documents…</div>
      ) : docs.length === 0 ? (
        <div style={{ textAlign: "center", padding: 80 }}>
          <div style={{ width: 56, height: 56, borderRadius: 12, background: "var(--bg-elev-2)", border: "1px solid var(--border)", display: "flex", alignItems: "center", justifyContent: "center", margin: "0 auto 16px" }}>
            <svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--text-3)" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
              <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/>
            </svg>
          </div>
          <div style={{ fontSize: 14, fontWeight: 600, color: "var(--text-2)", marginBottom: 6 }}>No documents yet</div>
          <div style={{ fontSize: 13, color: "var(--text-3)" }}>Your service agreements and platform guides will appear here once published.</div>
        </div>
      ) : (
        <>
          <DocGroup title="Contracts & Agreements" items={contracts} />
          <DocGroup title="User Manuals" items={manuals} />
          <DocGroup title="Policies" items={policies} />
          <DocGroup title="Guides & Resources" items={guides} />
        </>
      )}

      {/* Preview modal */}
      {previewDoc && (
        <div style={{ position: "fixed", inset: 0, background: "rgba(0,0,0,0.6)", zIndex: 9999, display: "flex", alignItems: "center", justifyContent: "center", padding: 24 }}>
          <div style={{ background: "var(--bg-card-solid)", borderRadius: 12, width: "100%", maxWidth: 780, maxHeight: "90vh", display: "flex", flexDirection: "column", overflow: "hidden", border: "1px solid var(--border)" }}>
            {/* Header */}
            <div style={{ padding: "18px 24px", borderBottom: "1px solid var(--border)", display: "flex", justifyContent: "space-between", alignItems: "center", flexShrink: 0 }}>
              <div>
                <div style={{ fontWeight: 700, fontSize: 15, color: "var(--text)" }}>{previewDoc.name}</div>
                <div style={{ fontSize: 12, color: "var(--text-3)", marginTop: 2 }}>
                  {previewDoc.category} · v{previewDoc.version}
                  {previewDoc.status === "signed" && previewDoc.signed_at && ` · Acknowledged ${new Date(previewDoc.signed_at).toLocaleDateString("en-US", { month: "short", day: "numeric", year: "numeric" })}`}
                </div>
              </div>
              <button onClick={() => setPreviewDoc(null)} style={{ background: "none", border: "none", cursor: "pointer", color: "var(--text-3)", padding: 6 }}>
                <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
              </button>
            </div>
            {/* Document body */}
            <div style={{ flex: 1, overflow: "auto", padding: "28px 36px", background: "#fff", color: "#1e293b", fontSize: 14, lineHeight: 1.75 }}
              dangerouslySetInnerHTML={{ __html: previewDoc.body_html }}
            />
            {/* Footer */}
            {previewDoc.category === "contract" && previewDoc.status !== "signed" && (
              <div style={{ padding: "16px 24px", borderTop: "1px solid #e2e8f0", background: "#f8fafc", flexShrink: 0, display: "flex", alignItems: "center", gap: 14 }}>
                <div style={{ flex: 1, fontSize: 12.5, color: "#64748b", lineHeight: 1.5 }}>
                  By clicking Acknowledge, you confirm you have read and agree to this document.
                </div>
                <button
                  onClick={() => acknowledge(previewDoc)}
                  disabled={acknowledging}
                  style={{ background: "#059669", color: "#fff", border: "none", borderRadius: 7, padding: "10px 22px", fontSize: 13.5, fontWeight: 600, cursor: "pointer", whiteSpace: "nowrap" }}
                >
                  {acknowledging ? "Saving…" : "Acknowledge & Accept"}
                </button>
              </div>
            )}
            {previewDoc.status === "signed" && (
              <div style={{ padding: "12px 24px", borderTop: "1px solid #e2e8f0", background: "#f0fdf4", flexShrink: 0, display: "flex", alignItems: "center", gap: 10 }}>
                <svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="#059669" strokeWidth="2.5" strokeLinecap="round"><polyline points="20 6 9 17 4 12"/></svg>
                <span style={{ fontSize: 13, color: "#059669", fontWeight: 500 }}>
                  Acknowledged on {new Date(previewDoc.signed_at).toLocaleDateString("en-US", { month: "long", day: "numeric", year: "numeric" })}
                </span>
              </div>
            )}
          </div>
        </div>
      )}
    </div>
  );
}

Object.assign(window, { ConfigPage, PeriodPage, UsersPage, CustomizePage, ContactPage, DocumentsPage });
