/* =========================================================================
 *  Python Tutor — top-level AccessGate
 *  -----------------------------------------------------------------------
 *  Wraps the entire app. The site must NOT be publicly accessible — every
 *  visitor has to be Google-signed-in AND on the existing
 *  /access/config.allowedEmails allowlist before any product surface
 *  renders. The lone exception is /desktop-signin (the desktop OAuth
 *  handoff page); App() short-circuits to that route BEFORE wrapping
 *  with this gate, so SIGNED_OUT and PENDING users can still complete
 *  the loopback flow there.
 *
 *  State machine:
 *    INITIALIZING       → brief loader; auth state still resolving.
 *                         Avoids the sub-second flash of SIGNED_OUT on
 *                         hot reload.
 *    SIGNED_OUT         → full-screen "Continue with Google" card.
 *                         No marketing copy, no nav.
 *    SIGNED_IN_PENDING  → "Pending approval" card with the user's email
 *                         and a sign-out button. Fail-closed: every
 *                         non-allowed response (errors, unknown reasons,
 *                         pending_allowlist_approval) lands here.
 *    SIGNED_IN_ALLOWED  → render props.children — the real app.
 *
 *  Mirrors the gate-check pattern that account.jsx already uses for
 *  itself (see account.jsx:34-58); this just hoists the logic so it
 *  applies to every route except /desktop-signin.
 * =======================================================================*/

const { useState, useEffect, useCallback } = React;

const OWNER_EMAIL = "sethbenricks@gmail.com";

function AccessGate({ children }) {
  const [user, setUser] = useState(null);
  const [authReady, setAuthReady] = useState(false);
  // gate: 'idle' | 'loading' | 'allowed' | 'pending'
  const [gate, setGate] = useState("idle");
  const [signingIn, setSigningIn] = useState(false);

  // Auth subscription. lib/auth.js exposes onUserChange which wraps
  // onAuthStateChanged + waitForFirebase, so this works whether the
  // ESM SDK has finished initializing yet or not.
  useEffect(() => {
    const off = window.PYTHON_TUTOR_AUTH.onUserChange((u) => {
      setUser(u);
      setAuthReady(true);
    });
    return () => { try { off && off(); } catch {} };
  }, []);

  // Run the allowlist check whenever the signed-in uid changes. Reset
  // the gate to idle when the user signs out so we don't flash stale
  // "allowed" state under the SIGNED_OUT card on next sign-in.
  useEffect(() => {
    if (!user) { setGate("idle"); return; }
    let cancelled = false;
    setGate("loading");
    window.PYTHON_TUTOR_FUNCTIONS.checkAllowlist()
      .then((res) => {
        if (cancelled) return;
        // Fail-closed: only `{ allowed: true }` unlocks the app.
        // pending_allowlist_approval, unknown_error, missing reason —
        // all map to "pending" so an error never accidentally shows
        // the app to an unapproved user.
        if (res && res.allowed) setGate("allowed");
        else setGate("pending");
      })
      .catch((err) => {
        if (cancelled) return;
        console.warn("[python-tutor] checkAllowlist failed:", err);
        setGate("pending");
      });
    return () => { cancelled = true; };
  }, [user && user.uid]);

  const onSignIn = useCallback(async () => {
    setSigningIn(true);
    try { await window.PYTHON_TUTOR_AUTH.signInWithGoogle(); }
    catch (err) { console.warn("[python-tutor] sign-in failed:", err); }
    finally { setSigningIn(false); }
  }, []);

  const onSignOut = useCallback(async () => {
    try { await window.PYTHON_TUTOR_AUTH.signOut(); } catch {}
  }, []);

  // 1. INITIALIZING — auth listener hasn't reported yet, OR user just
  //    signed in and the allowlist round-trip is still in flight. Shows
  //    the animated brandmark instead of a generic spinner so the wait
  //    feels intentional and on-brand.
  if (!authReady || (user && gate === "loading")) {
    return (
      <div className="pt-page">
        <main className="pt-main">
          <section className="pt-soon" style={{ alignItems: "center", paddingTop: 96 }}>
            <div className="pt-gate-mark">
              <AnimatedPyBrand size={120} />
            </div>
          </section>
        </main>
      </div>
    );
  }

  // 2. SIGNED_OUT — no user. Single CTA, no marketing copy, no nav.
  //    Animated brandmark on top so the sign-in screen is an actual
  //    brand moment rather than a bare button.
  if (!user) {
    return (
      <div className="pt-page">
        <main className="pt-main">
          <section className="pt-soon" style={{ alignItems: "center", textAlign: "center", paddingTop: 56 }}>
            <div className="pt-gate-mark">
              <AnimatedPyBrand size={120} />
            </div>
            <div className="ct-eyebrow">Python Tutor — private beta</div>
            <h1 className="pt-soon-h1" style={{ maxWidth: 18 + "ch" }}>
              Sign in to access Python Tutor.
            </h1>
            <div className="pt-soon-cta" style={{ justifyContent: "center" }}>
              <button
                className="ct-btn ct-btn-primary ct-btn-lg"
                onClick={onSignIn}
                disabled={signingIn}>
                {signingIn ? "Opening Google sign-in…" : "Continue with Google"}
              </button>
            </div>
          </section>
        </main>
      </div>
    );
  }

  // 3. SIGNED_IN_PENDING — fail-closed for any non-allowed response.
  if (gate !== "allowed") {
    const email = user.email || "your account";
    return (
      <div className="pt-page">
        <main className="pt-main">
          <section className="pt-soon" style={{ alignItems: "center", textAlign: "center", paddingTop: 56 }}>
            <div className="pt-gate-mark">
              <PyBrand size={56} withWord={false} />
            </div>
            <div className="ct-eyebrow">Pending approval</div>
            <h1 className="pt-soon-h1" style={{ maxWidth: 22 + "ch" }}>
              Your access hasn't been approved yet.
            </h1>
            <p className="pt-soon-sub" style={{ textAlign: "center" }}>
              <span className="ct-mono">{email}</span> isn't on the allowlist
              yet. Contact Seth at{" "}
              <a className="pt-footer-link" href={`mailto:${OWNER_EMAIL}?subject=${encodeURIComponent("Python Tutor access request")}`}>
                {OWNER_EMAIL}
              </a>{" "}
              to request access.
            </p>
            <div className="pt-soon-cta" style={{ justifyContent: "center" }}>
              <button className="ct-btn ct-btn-lg" onClick={onSignOut}>
                Sign out
              </button>
            </div>
          </section>
        </main>
      </div>
    );
  }

  // 4. SIGNED_IN_ALLOWED — let the app through.
  return children;
}

window.AccessGate = AccessGate;
