/* Connection — the screen that answers "is Iwakiri actually talking to my
   database, and if not, which of the five reasons is it?"
   ============================================================================

   Everything else in this prototype is a screen for an operator. This one is
   for whoever is standing the platform up, and it exists because an empty
   table looks identical whether the cause is:

     1. SUPABASE_URL / ANON_KEY not set        -> kind "config"
     2. set, but the migration was never run   -> 42P01
     3. run, but nobody is signed in           -> RLS denies, zero rows
     4. signed in, but that auth user has no   -> current_app_user() is empty,
        row in `users`                            so every policy denies
     5. all of the above fine, nothing seeded  -> genuinely zero rows

   A table component shows the same blank panel for all five. sb.diagnose()
   distinguishes them and this screen renders the answer.

   No writes, and no money: it signs in, reads, and reports. Sign-in is the
   only POST, and without it there is no read path at all.
*/

const SBC_LEVELS = { 0: "Super admin", 1: "Affiliate", 2: "Operator", 4: "Customer care",
                     6: "Administration", 8: "Agent", 9: "Regulator", 10: "Promoter",
                     15: "Shop", 20: "Cashier", 30: "Player" };

const sbcMoney = (n) => Number(n || 0).toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

const SbcVerdict = ({ d }) => {
  const tone = !d.configured ? "warn"
    : d.keyRole === "service_role" ? "bad"
    : d.checks.some(c => !c.ok) ? "bad"
    : d.checks.some(c => c.ok && c.rows === 0 && c.name !== "balance_drift") ? "warn"
    : "good";
  return (
    <div className={`sbc-verdict sbc-verdict--${tone}`} role="status">
      <Icon name={tone === "good" ? "check" : "alert"} size={16}/>
      <span>{d.verdict}</span>
    </div>
  );
};

const SbcSignIn = ({ onDone }) => {
  const [email, setEmail] = React.useState("");
  const [pw, setPw] = React.useState("");
  const [busy, setBusy] = React.useState(false);
  const [err, setErr] = React.useState(null);

  const submit = async (e) => {
    e.preventDefault();
    setBusy(true); setErr(null);
    const r = await window.sb.signIn(email.trim(), pw);
    setBusy(false);
    if (!r.ok) { setErr(r.error.message); return; }
    setPw("");
    onDone && onDone();
  };

  return (
    <form className="sbc-signin" onSubmit={submit}>
      <div className="sbc-signin__row">
        <label>
          <span>Email</span>
          <input type="email" value={email} autoComplete="username"
                 onChange={e => setEmail(e.target.value)} placeholder="you@yourdomain.com" required/>
        </label>
        <label>
          <span>Password</span>
          <input type="password" value={pw} autoComplete="current-password"
                 onChange={e => setPw(e.target.value)} required/>
        </label>
        <button className="btn btn--primary" type="submit" disabled={busy}>
          {busy ? "Signing in…" : "Sign in"}
        </button>
      </div>
      {err && <div className="sbc-signin__err" role="alert">{err}</div>}
      <div className="sbc-signin__note">
        The account is the one in Supabase → Authentication → Users. It must be
        confirmed, and its email must match a row in <code>users</code> —
        that link is what every RLS policy resolves through.
      </div>
    </form>
  );
};

const DevSupabase = () => {
  const [nonce, setNonce] = React.useState(0);
  const refresh = () => setNonce(n => n + 1);

  const diag = useHrsFetch(() => window.sb.diagnose(), [nonce]);
  const users = useHrsFetch(() => window.sb.users({ limit: 50 }), [nonce]);
  const bals = useHrsFetch(() => window.sb.balances({ limit: 50 }), [nonce]);
  const led = useHrsFetch(() => window.sb.ledger({ limit: 25 }), [nonce]);

  React.useEffect(() => {
    const h = () => refresh();
    window.addEventListener("sb:session", h);
    return () => window.removeEventListener("sb:session", h);
  }, []);

  const d = diag.data;
  const signedIn = !!(d && d.signedIn);

  return (
    <HrsShell
      title="Connection"
      subtitle="Iwakiri's own database — Postgres on Supabase, read through PostgREST with row-level security."
      gateNote="Not a real-platform screen. It exists to make the difference between “no data” and “not connected” visible, because a table cannot show it."
      actions={
        <>
          <button className="btn" onClick={refresh}>Re-run checks</button>
          {signedIn && (
            <button className="btn" onClick={async () => { await window.sb.signOut(); refresh(); }}>
              Sign out
            </button>
          )}
        </>
      }
    >
      {/* ---------------------------------------------------------- verdict */}
      <HrsAsync state={diag} skeletonRows={4} skeletonCols={3}>
        {(dd) => (
          <>
            <SbcVerdict d={dd}/>

            <HrsSection title="Configuration" sub="Set in index.html. Both must be present before anything below runs live.">
              <div className="sbc-kv">
                <div><span>Mode</span><b>{dd.configured ? "live" : "not configured"}</b></div>
                <div><span>Project URL</span><b>{dd.url || <em>not set</em>}</b></div>
                <div><span>Key role</span>
                  <b className={dd.keyRole === "service_role" ? "sbc-bad" : ""}>
                    {dd.keyRole || <em>not set</em>}
                  </b>
                </div>
                <div><span>Signed in as</span><b>{dd.email || <em>nobody</em>}</b></div>
                <div><span>Session</span>
                  <b>{!dd.signedIn ? "none" : dd.expired ? "expired — sign in again" : "valid"}</b>
                </div>
              </div>
              {dd.keyRole === "service_role" && (
                <div className="sbc-signin__err" role="alert">
                  That is the <code>service_role</code> key. It carries BYPASSRLS: every
                  tenant's data would be readable by anyone who opens devtools. Replace it
                  with the anon key and rotate it in the dashboard.
                </div>
              )}
              {!dd.configured && (
                <div className="sbc-signin__note">
                  There is no fallback data, so every screen is empty until this is set.
                  Fill in <code>window.SUPABASE_URL</code> and{" "}
                  <code>window.SUPABASE_ANON_KEY</code> in <code>index.html</code>, then reload.
                </div>
              )}
            </HrsSection>

            {dd.configured && !dd.signedIn && (
              <HrsSection title="Sign in" sub="RLS keys off auth.uid(). Signed out, every table reads as empty — which is correct, not broken.">
                <SbcSignIn onDone={refresh}/>
              </HrsSection>
            )}

            <HrsSection title="Checks" sub="In order. The first failure is the one to fix; the rest usually follow from it.">
              <HrsTable
                rowKey={(r) => r.name}
                columns={[
                  { key: "name", label: "Check" },
                  { key: "state", label: "Result", render: (r) => (
                      <span className={r.ok ? "sbc-good" : "sbc-bad"}>
                        {r.ok ? "ok" : (r.kind || "failed")}
                      </span>
                    ) },
                  { key: "rows", label: "Rows", align: "right",
                    render: (r) => r.ok ? (r.total != null ? `${r.rows} of ${r.total}` : String(r.rows)) : "—" },
                  { key: "detail", label: "Detail",
                    render: (r) => r.error || r.hint || "" },
                ]}
                rows={dd.checks}
              />
            </HrsSection>
          </>
        )}
      </HrsAsync>

      {/* ------------------------------------------------------------ data */}
      <HrsSection title="users" sub="Ordered by hierarchy path. RLS returns only your own subtree — there is no client-side filter here to remove.">
        <HrsAsync state={users} empty="No users visible. Either nothing is seeded, or your auth user is not linked to a row in `users`."
                  skeletonCols={6}>
          {(rows) => (
            <HrsTable
              rowKey="id"
              columns={[
                { key: "id", label: "ID", align: "right" },
                { key: "path", label: "Path" },
                { key: "username", label: "Username" },
                { key: "user_level", label: "Role", render: (r) => SBC_LEVELS[r.user_level] || r.user_level },
                { key: "skin_id", label: "Skin", align: "right" },
                { key: "currency", label: "Currency" },
              ]}
              rows={rows}
            />
          )}
        </HrsAsync>
      </HrsSection>

      <HrsSection title="user_balances" sub="real_total and available are generated columns — they cannot drift from their inputs, because nothing can write them.">
        <HrsAsync state={bals} empty="No balances." skeletonCols={6}>
          {(rows) => (
            <HrsTable
              rowKey="user_id"
              columns={[
                { key: "user_id", label: "ID", align: "right" },
                { key: "username", label: "Username", render: (r) => (r.users && r.users.username) || "—" },
                { key: "balance_withdrawable", label: "Withdrawable", align: "right", render: (r) => sbcMoney(r.balance_withdrawable) },
                { key: "credits", label: "Credits", align: "right", render: (r) => sbcMoney(r.credits) },
                { key: "bonus", label: "Bonus", align: "right", render: (r) => sbcMoney(r.bonus) },
                { key: "available", label: "Available", align: "right", render: (r) => sbcMoney(r.available) },
              ]}
              rows={rows}
            />
          )}
        </HrsAsync>
      </HrsSection>

      <HrsSection title="ledger_entries" sub="Append-only: anon holds no UPDATE or DELETE. Every row was written by post_transaction() in the same transaction as the balance it stamped.">
        <HrsAsync state={led} empty="No ledger entries." skeletonCols={6}>
          {(rows) => (
            <HrsTable
              rowKey="id"
              columns={[
                { key: "id", label: "#", align: "right" },
                { key: "username", label: "User", render: (r) => (r.user && r.user.username) || r.user_id },
                { key: "type_id", label: "Type", align: "right" },
                { key: "wallet", label: "Wallet" },
                { key: "amount", label: "Amount", align: "right", render: (r) => sbcMoney(r.amount) },
                { key: "balance_after", label: "Balance after", align: "right", render: (r) => sbcMoney(r.balance_after) },
                { key: "description", label: "Description" },
              ]}
              rows={rows}
            />
          )}
        </HrsAsync>
      </HrsSection>
    </HrsShell>
  );
};
