/* GroupSync.jsx — Google group sync status on the Access page (0143, admin only).
   Documents open in Google Drive, and Drive access comes from two Google groups that
   the group-sync function keeps in step with this Access list. Shows the latest run per
   group (or what a dry run WOULD do) and a Sync now button. */
(function () {
  const { Card, Button } = window.LawCrimeDesignSystem_e18d68;
  const sb = window.SB;
  const fmt = (t) => new Date(t).toLocaleString("en-US", { timeZone: "America/New_York", month: "short", day: "numeric", hour: "numeric", minute: "2-digit" });
  const list = (a) => (a && a.length ? a.join(", ") : "none");

  async function latest() {
    const { data, error } = await sb.from("group_sync_runs").select("*").order("ran_at", { ascending: false }).limit(20);
    if (error) throw error;
    const seen = {}; const out = [];
    (data || []).forEach((r) => { if (!seen[r.group_email]) { seen[r.group_email] = 1; out.push(r); } });
    return out;
  }
  async function runNow() {
    const { data: { session } } = await sb.auth.getSession();
    const res = await fetch(`${window.SB_URL}/functions/v1/group-sync`, {
      method: "POST",
      headers: { "Content-Type": "application/json", "Authorization": `Bearer ${session && session.access_token}`, "apikey": window.SB_KEY },
      body: "{}",
    });
    const body = await res.json().catch(() => ({}));
    if (!res.ok) throw new Error(body.error || `Sync failed (${res.status})`);
    return body;
  }

  function GroupSync() {
    const [runs, setRuns] = React.useState(null);
    const [busy, setBusy] = React.useState(false);
    const [err, setErr] = React.useState(null);
    const load = () => latest().then(setRuns).catch((e) => { setRuns([]); setErr(e.message || String(e)); });
    React.useEffect(() => { load(); }, []);
    async function sync() {
      setBusy(true); setErr(null);
      try { await runNow(); await load(); } catch (e) { setErr(e.message || String(e)); } finally { setBusy(false); }
    }
    return (
      <Card style={{ marginTop: 12 }}><Card.Body>
        <div className="gs-head">
          <div>
            <b>Google groups for documents</b>
            <div className="gs-sub">Ledger keeps these groups in step with this list, so people can open documents in Drive. It runs after every change here and every 30 minutes.</div>
          </div>
          <Button variant="secondary" icon="refresh-cw" onClick={sync} disabled={busy}>{busy ? "Syncing…" : "Sync now"}</Button>
        </div>
        {err && <div className="login__err" style={{ margin: "8px 0" }}>{err}</div>}
        {runs === null ? <div className="gs-sub">Loading…</div> : runs.length === 0 ? <div className="gs-sub">No sync has run yet.</div> : (
          <table className="gs-table">
            <thead><tr><th>Group</th><th>Last run</th><th>{runs.some((r) => r.dry_run) ? "Added (or would add)" : "Added"}</th><th>{runs.some((r) => r.dry_run) ? "Removed (or would remove)" : "Removed"}</th><th>Needs attention</th></tr></thead>
            <tbody>
              {runs.map((r) => (
                <tr key={r.id}>
                  <td><code>{r.group_email}</code>{r.dry_run && <span className="gs-dry">dry run</span>}</td>
                  <td className="gs-nowrap">{fmt(r.ran_at)}<div className="gs-sub">{r.current ?? "?"} in group · {r.desired} should be</div></td>
                  <td>{list(r.added)}</td>
                  <td>{list(r.removed)}</td>
                  <td>
                    {r.held_back && r.held_back.length > 0 && <div>Held back (over the removal cap): {r.held_back.join(", ")}</div>}
                    {(r.errors || []).map((e, i) => <div key={i} className="gs-err">{e.email ? `${e.email}: ` : ""}{e.error}</div>)}
                    {!(r.held_back && r.held_back.length) && !(r.errors || []).length && <span className="gs-sub">—</span>}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </Card.Body></Card>
    );
  }
  window.LedgerGroupSync = GroupSync;
})();
