// public/admin.jsx — Admin console (superadmin + company_admin).
//
// Users live in Clerk; this screen reads them via /api/admin/users (enriched with
// our credit balances + case counts) and mutates via /api/admin/actions. The
// server enforces role + company scope on every call — the client only decides
// whether to show controls. Follows the pricing.jsx no-build pattern.

const { useState: useAdminState, useEffect: useAdminEffect, useCallback: useAdminCb } = React;

const ADMIN_PLAN_FALLBACK = [
  { slug: "free", label: "Free" },
  { slug: "pro", label: "Solopreneur" },
  { slug: "team", label: "Team" },
];
const ADMIN_ROLES = [
  { slug: "user", label: "User" },
  { slug: "company_admin", label: "Company admin" },
  { slug: "superadmin", label: "Superadmin" },
];
const PAGE_SIZE = 50;

function fmtDate(s) {
  if (!s) return "—";
  try { return new Date(s).toLocaleDateString(); } catch { return "—"; }
}

async function adminApi(path, opts = {}) {
  const headers = await window.Auth.apiHeaders(opts.headers || {});
  const resp = await fetch(path, { credentials: "same-origin", ...opts, headers });
  const data = await resp.json().catch(() => ({}));
  if (!resp.ok) throw new Error(data.error || `Request failed (${resp.status})`);
  return data;
}

function GrantCreditsModal({ row, onClose, onApplied }) {
  const [add, setAdd] = useAdminState("");
  const [setGrant, setSetGrant] = useAdminState("");
  const [busy, setBusy] = useAdminState(false);
  const [err, setErr] = useAdminState(null);

  async function apply() {
    const addCredits = Number(add) || 0;
    const grant = setGrant === "" ? null : Number(setGrant);
    if (!addCredits && grant == null) { setErr("Enter an amount to add, or a grant balance to set."); return; }
    setBusy(true); setErr(null);
    try {
      const data = await adminApi("/api/admin/actions", {
        method: "POST",
        body: JSON.stringify({ action: "grant_credits", userId: row.id, addCredits, setGrant: grant }),
      });
      onApplied(data.credits);
    } catch (e) { setErr(e.message); } finally { setBusy(false); }
  }

  return (
    <div className="admin-modal-backdrop" onClick={onClose}
      style={{ position: "fixed", inset: 0, background: "rgba(20,20,40,0.45)", display: "flex", alignItems: "center", justifyContent: "center", zIndex: 50 }}>
      <div className="admin-modal" onClick={(e) => e.stopPropagation()}
        style={{ background: "#fff", borderRadius: 14, padding: 24, width: 380, maxWidth: "92vw", boxShadow: "0 20px 60px rgba(0,0,0,0.25)" }}>
        <h3 className="display-sm" style={{ margin: "0 0 4px", fontSize: 18 }}>Adjust credits</h3>
        <p style={{ margin: "0 0 16px", fontSize: 13, opacity: 0.7 }}>
          {row.name} · {row.email || row.id}<br/>
          Now: {row.credits ? Math.floor(row.credits.remaining) : 0} remaining
          {row.credits ? ` (${Math.floor(row.credits.grantRemaining)} grant)` : ""}
        </p>
        <label style={{ display: "block", fontSize: 12, fontWeight: 600, marginBottom: 4 }}>Add credits (+/−)</label>
        <input type="number" value={add} onChange={(e) => setAdd(e.target.value)} placeholder="e.g. 500"
          style={{ width: "100%", padding: "8px 10px", marginBottom: 12, borderRadius: 8, border: "1px solid #ccc" }}/>
        <label style={{ display: "block", fontSize: 12, fontWeight: 600, marginBottom: 4 }}>or set grant balance to</label>
        <input type="number" value={setGrant} onChange={(e) => setSetGrant(e.target.value)} placeholder="absolute, e.g. 1000"
          style={{ width: "100%", padding: "8px 10px", marginBottom: 12, borderRadius: 8, border: "1px solid #ccc" }}/>
        {err && <div style={{ color: "#c0392b", fontSize: 12, marginBottom: 10 }}>{err}</div>}
        <div style={{ display: "flex", gap: 8, justifyContent: "flex-end" }}>
          <button className="btn-secondary" onClick={onClose} disabled={busy}>Cancel</button>
          <button className="btn-primary" onClick={apply} disabled={busy}>{busy ? "Applying…" : "Apply"}</button>
        </div>
      </div>
    </div>
  );
}

function CasesDrawer({ row, onClose }) {
  const [cases, setCases] = useAdminState(null);
  const [err, setErr] = useAdminState(null);
  useAdminEffect(() => {
    let alive = true;
    adminApi("/api/admin/actions", { method: "POST", body: JSON.stringify({ action: "list_cases", userId: row.id }) })
      .then((d) => { if (alive) setCases(d.cases || []); })
      .catch((e) => { if (alive) setErr(e.message); });
    return () => { alive = false; };
  }, [row.id]);
  return (
    <tr className="admin-cases-row">
      <td colSpan={7} style={{ background: "#f7f7fb", padding: "12px 16px" }}>
        <div style={{ display: "flex", justifyContent: "space-between", alignItems: "center", marginBottom: 8 }}>
          <strong style={{ fontSize: 13 }}>Cases for {row.name}</strong>
          <button className="app-topbar-link" onClick={onClose} style={{ fontSize: 12 }}>Close</button>
        </div>
        {err && <div style={{ color: "#c0392b", fontSize: 12 }}>{err}</div>}
        {!cases && !err && <div style={{ fontSize: 12, opacity: 0.6 }}>Loading…</div>}
        {cases && cases.length === 0 && <div style={{ fontSize: 12, opacity: 0.6 }}>No cases yet.</div>}
        {cases && cases.length > 0 && (
          <table style={{ width: "100%", fontSize: 12, borderCollapse: "collapse" }}>
            <thead><tr style={{ textAlign: "left", opacity: 0.6 }}>
              <th style={{ padding: "4px 8px" }}>Title</th><th style={{ padding: "4px 8px" }}>Type</th>
              <th style={{ padding: "4px 8px" }}>Phase</th><th style={{ padding: "4px 8px" }}>Updated</th>
            </tr></thead>
            <tbody>
              {cases.map((c) => (
                <tr key={c.id} style={{ borderTop: "1px solid #e6e6ef" }}>
                  <td style={{ padding: "4px 8px" }}>{c.title || "—"}</td>
                  <td style={{ padding: "4px 8px" }}>{c.archetypeLabel || "—"}</td>
                  <td style={{ padding: "4px 8px" }}>{c.phase || "—"}</td>
                  <td style={{ padding: "4px 8px" }}>{fmtDate(c.updatedAt)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </td>
    </tr>
  );
}

function AdminScreen({ user, adminContext, onBack, onOpenSettings, onSignOut }) {
  const isSuper = adminContext?.role === "superadmin";
  const [rows, setRows] = useAdminState([]);
  const [total, setTotal] = useAdminState(0);
  const [offset, setOffset] = useAdminState(0);
  const [query, setQuery] = useAdminState("");
  const [search, setSearch] = useAdminState("");
  const [loading, setLoading] = useAdminState(true);
  const [error, setError] = useAdminState(null);
  const [planOptions, setPlanOptions] = useAdminState(ADMIN_PLAN_FALLBACK);
  const [creditModal, setCreditModal] = useAdminState(null);
  const [expanded, setExpanded] = useAdminState(null);
  const [rowBusy, setRowBusy] = useAdminState(null);

  useAdminEffect(() => {
    window.Auth.getConfig?.().then((cfg) => {
      const plans = cfg?.billing?.plans;
      if (Array.isArray(plans) && plans.length) setPlanOptions(plans.map((p) => ({ slug: p.slug, label: p.label })));
    }).catch(() => {});
  }, []);

  const load = useAdminCb(async () => {
    setLoading(true); setError(null);
    try {
      const qs = new URLSearchParams({ limit: String(PAGE_SIZE), offset: String(offset) });
      if (query) qs.set("query", query);
      const data = await adminApi(`/api/admin/users?${qs.toString()}`);
      setRows(data.users || []);
      setTotal(data.totalCount || 0);
    } catch (e) { setError(e.message); } finally { setLoading(false); }
  }, [offset, query]);

  useAdminEffect(() => { load(); }, [load]);

  async function doAction(row, payload, label) {
    setRowBusy(row.id + ":" + label); setError(null);
    try {
      await adminApi("/api/admin/actions", { method: "POST", body: JSON.stringify({ userId: row.id, ...payload }) });
      await load();
    } catch (e) { setError(e.message); } finally { setRowBusy(null); }
  }

  function onChangePlan(row, plan) {
    if (plan === row.plan) return;
    if (!window.confirm(`Change ${row.name}'s plan to "${plan}"?`)) return;
    doAction(row, { action: "set_plan", plan }, "plan");
  }
  function onChangeRole(row, role) {
    const current = row.role || "user";
    if (role === current) return;
    if (!window.confirm(`Set ${row.name}'s role to "${role}"?`)) return;
    doAction(row, { action: "set_role", role }, "role");
  }
  function onToggleBan(row) {
    const status = row.banned ? "unban" : "ban";
    if (!window.confirm(`${row.banned ? "Unblock" : "Block"} ${row.name}?`)) return;
    doAction(row, { action: "set_status", status }, "status");
  }

  const cell = { padding: "10px 12px", borderTop: "1px solid #ececf4", fontSize: 13, verticalAlign: "middle" };
  const th = { padding: "8px 12px", textAlign: "left", fontSize: 11, textTransform: "uppercase", letterSpacing: ".04em", opacity: 0.55 };

  return (
    <div className="admin-screen">
      <AppTopBar user={user} active="admin" onOpenWorkspace={onBack} onOpenSettings={onOpenSettings} onSignOut={onSignOut}/>
      <main className="admin-main" style={{ maxWidth: 1180, margin: "0 auto", padding: "28px 24px 64px" }}>
        <button className="app-topbar-link" onClick={onBack} style={{ marginBottom: 14 }}>
          <IconText name="arrow-left">Back</IconText>
        </button>

        <header style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", gap: 16, flexWrap: "wrap", marginBottom: 20 }}>
          <div>
            <h1 className="display-sm" style={{ margin: "0 0 6px" }}>Admin</h1>
            <p style={{ margin: 0, opacity: 0.7, fontSize: 13 }}>
              {adminContext?.role === "company_admin"
                ? `Managing ${adminContext?.company || "your company"}'s users.`
                : "All users across the platform."}{" "}
              {total} total.
            </p>
          </div>
          <form onSubmit={(e) => { e.preventDefault(); setOffset(0); setQuery(search.trim()); }} style={{ display: "flex", gap: 8 }}>
            <input value={search} onChange={(e) => setSearch(e.target.value)} placeholder="Search name or email"
              style={{ padding: "8px 12px", borderRadius: 8, border: "1px solid #ccc", width: 240 }}/>
            <button className="btn-secondary" type="submit">Search</button>
          </form>
        </header>

        {error && <div style={{ color: "#c0392b", fontSize: 13, marginBottom: 12 }}>{error}</div>}

        <div style={{ overflowX: "auto", border: "1px solid #ececf4", borderRadius: 12 }}>
          <table style={{ width: "100%", borderCollapse: "collapse", minWidth: 920 }}>
            <thead>
              <tr>
                <th style={th}>User</th>
                <th style={th}>Company</th>
                <th style={th}>Plan</th>
                {isSuper && <th style={th}>Role</th>}
                <th style={th}>Credits</th>
                <th style={th}>Cases</th>
                <th style={th}>Actions</th>
              </tr>
            </thead>
            <tbody>
              {loading && <tr><td style={cell} colSpan={7}>Loading…</td></tr>}
              {!loading && rows.length === 0 && <tr><td style={cell} colSpan={7}>No users found.</td></tr>}
              {!loading && rows.map((row) => (
                <React.Fragment key={row.id}>
                  <tr style={{ opacity: row.banned ? 0.55 : 1 }}>
                    <td style={cell}>
                      <div style={{ fontWeight: 600 }}>{row.name}{row.banned && <span style={{ color: "#c0392b", fontSize: 11 }}> · blocked</span>}</div>
                      <div style={{ fontSize: 12, opacity: 0.6 }}>{row.email || row.id}</div>
                      <div style={{ fontSize: 11, opacity: 0.45 }}>Joined {fmtDate(row.createdAt)} · active {fmtDate(row.lastActiveAt)}</div>
                    </td>
                    <td style={cell}>{row.company || "—"}</td>
                    <td style={cell}>
                      <select value={row.plan} onChange={(e) => onChangePlan(row, e.target.value)}
                        disabled={rowBusy === row.id + ":plan"}
                        style={{ padding: "5px 8px", borderRadius: 7, border: "1px solid #ccc", textTransform: "capitalize" }}>
                        {planOptions.map((p) => <option key={p.slug} value={p.slug}>{p.label}</option>)}
                      </select>
                    </td>
                    {isSuper && (
                      <td style={cell}>
                        <select value={row.role || "user"} onChange={(e) => onChangeRole(row, e.target.value)}
                          disabled={rowBusy === row.id + ":role"}
                          style={{ padding: "5px 8px", borderRadius: 7, border: "1px solid #ccc" }}>
                          {ADMIN_ROLES.map((r) => <option key={r.slug} value={r.slug}>{r.label}</option>)}
                        </select>
                      </td>
                    )}
                    <td style={cell}>
                      {row.credits ? (
                        <span title={`${row.credits.used} used · ${Math.floor(row.credits.grantRemaining)} grant`}>
                          <strong>{Math.floor(row.credits.remaining)}</strong> <span style={{ opacity: 0.5, fontSize: 11 }}>left</span>
                        </span>
                      ) : "—"}
                    </td>
                    <td style={cell}>
                      <button className="app-topbar-link" style={{ fontSize: 12 }}
                        onClick={() => setExpanded(expanded === row.id ? null : row.id)}>
                        {row.caseCount} {expanded === row.id ? "▲" : "▾"}
                      </button>
                    </td>
                    <td style={cell}>
                      <div style={{ display: "flex", gap: 6, flexWrap: "wrap" }}>
                        <button className="btn-secondary" style={{ fontSize: 12, padding: "4px 8px" }}
                          onClick={() => setCreditModal(row)}>Credits</button>
                        <button className="btn-secondary" style={{ fontSize: 12, padding: "4px 8px", color: row.banned ? "#1E1E5A" : "#c0392b" }}
                          disabled={rowBusy === row.id + ":status"}
                          onClick={() => onToggleBan(row)}>{row.banned ? "Unblock" : "Block"}</button>
                      </div>
                    </td>
                  </tr>
                  {expanded === row.id && <CasesDrawer row={row} onClose={() => setExpanded(null)}/>}
                </React.Fragment>
              ))}
            </tbody>
          </table>
        </div>

        {total > PAGE_SIZE && (
          <div style={{ display: "flex", gap: 10, justifyContent: "center", alignItems: "center", marginTop: 16 }}>
            <button className="btn-secondary" disabled={offset === 0} onClick={() => setOffset(Math.max(0, offset - PAGE_SIZE))}>Previous</button>
            <span style={{ fontSize: 12, opacity: 0.6 }}>{offset + 1}–{Math.min(offset + PAGE_SIZE, total)} of {total}</span>
            <button className="btn-secondary" disabled={offset + PAGE_SIZE >= total} onClick={() => setOffset(offset + PAGE_SIZE)}>Next</button>
          </div>
        )}
      </main>

      {creditModal && (
        <GrantCreditsModal
          row={creditModal}
          onClose={() => setCreditModal(null)}
          onApplied={(credits) => {
            setRows((rs) => rs.map((r) => r.id === creditModal.id ? { ...r, credits: { ...r.credits, ...credits } } : r));
            setCreditModal(null);
          }}
        />
      )}
    </div>
  );
}

window.AdminScreen = AdminScreen;
