/* ============================================================
   auth.jsx — Google sign-in gate.
   Real Google OAuth is wired up; while no Client ID is set, a
   dev account-picker lets you test access control immediately.

   Access is granted ONLY to emails listed in People (Designers tab).
   The person's "access" field (admin / manager / designer) decides
   what they can do once inside.
   ============================================================ */
(function () {
  const { useState, useEffect, useRef } = React;

  /* ======================= CONFIG ======================= *
   * Paste your Google OAuth Client ID below after you deploy this app
   * to your own domain. Create one here:
   *   https://console.cloud.google.com/apis/credentials
   *   → "Create credentials" → "OAuth client ID" → type "Web application"
   *   → add your deployed origin under "Authorized JavaScript origins"
   *
   * While this stays empty, the app shows a DEV sign-in (account picker)
   * so the access logic is fully testable right now.
   * ====================================================== */
  const GOOGLE_CLIENT_ID = "903744215503-n5b000doqj9vv3sjenquelcpjubppaea.apps.googleusercontent.com";

  const AUTH_KEY = "nove8_auth_v1";
  const PEOPLE_KEY = "nove8_designers_v1";

  const norm = (e) => (e || "").trim().toLowerCase();

  const PEOPLE_API = "/api/people";

  function peopleFromState(s) {
    if (!s) return null;
    const ds = Array.isArray(s.designers) ? s.designers : [];
    const ms = Array.isArray(s.managers) ? s.managers : [];
    return [
      ...ds.map((d) => ({ id: d.id, name: d.name, email: d.email, access: d.access || "designer", position: d.position, kind: "designer", handles: (Array.isArray(d.handles) && d.handles.length) ? d.handles : [d.name] })),
      ...ms.map((m) => ({ id: m.id, name: m.name, email: m.email, access: m.access || "manager", position: "Manager", kind: "manager" })),
    ];
  }

  function loadPeople() {
    try { return peopleFromState(JSON.parse(localStorage.getItem(PEOPLE_KEY) || "null")) || []; }
    catch (e) { return []; }
  }

  // Server is the shared source of truth for roster + access roles. Falls back
  // to the local cache only when the API is unreachable, so a transient network
  // blip can't lock the whole team out.
  async function fetchServerPeople() {
    try {
      const r = await fetch(PEOPLE_API, { cache: "no-store" });
      if (!r.ok) return null;
      const j = await r.json();
      return peopleFromState(j && j.state);
    } catch (e) { return null; }
  }
  function accessOf(person) {
    if (!person) return null;
    if (person.access === "admin") return "admin";
    if (person.access === "manager" || person.kind === "manager") return "manager";
    return "designer";
  }

  function decodeJwt(token) {
    try {
      const base = token.split(".")[1].replace(/-/g, "+").replace(/_/g, "/");
      const json = decodeURIComponent(atob(base).split("").map((c) => "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2)).join(""));
      return JSON.parse(json);
    } catch (e) { return null; }
  }

  function loadAuth() { try { return JSON.parse(localStorage.getItem(AUTH_KEY) || "null"); } catch (e) { return null; } }
  function saveAuth(a) { try { a ? localStorage.setItem(AUTH_KEY, JSON.stringify(a)) : localStorage.removeItem(AUTH_KEY); } catch (e) {} }

  const initials = (n) => (n || "?").split(" ").filter(Boolean).slice(0, 2).map((w) => w[0].toUpperCase()).join("");

  function GoogleG({ size = 18 }) {
    return (
      <svg width={size} height={size} viewBox="0 0 48 48" aria-hidden="true">
        <path fill="#4285F4" d="M45.12 24.5c0-1.56-.14-3.06-.4-4.5H24v8.51h11.84c-.51 2.75-2.06 5.08-4.39 6.64v5.52h7.11c4.16-3.83 6.56-9.47 6.56-16.17z"/>
        <path fill="#34A853" d="M24 46c5.94 0 10.92-1.97 14.56-5.33l-7.11-5.52c-1.97 1.32-4.49 2.1-7.45 2.1-5.73 0-10.58-3.87-12.31-9.07H4.34v5.7C7.96 41.07 15.4 46 24 46z"/>
        <path fill="#FBBC05" d="M11.69 28.18c-.44-1.32-.69-2.73-.69-4.18s.25-2.86.69-4.18v-5.7H4.34A21.99 21.99 0 0 0 2 24c0 3.55.85 6.91 2.34 9.88l7.35-5.7z"/>
        <path fill="#EA4335" d="M24 9.75c3.23 0 6.13 1.11 8.41 3.29l6.31-6.31C34.91 2.97 29.93 1 24 1 15.4 1 7.96 5.93 4.34 13.12l7.35 5.7c1.73-5.2 6.58-9.07 12.31-9.07z"/>
      </svg>
    );
  }

  function LoginScreen({ onSignIn }) {
    const btnRef = useRef(null);
    const [gReady, setGReady] = useState(false);
    const [manual, setManual] = useState(false);
    const [email, setEmail] = useState("");
    const people = loadPeople();

    useEffect(() => {
      if (!GOOGLE_CLIENT_ID) return; // dev mode → skip GIS
      let tries = 0;
      const t = setInterval(() => {
        if (window.google && window.google.accounts && window.google.accounts.id) {
          clearInterval(t);
          window.google.accounts.id.initialize({
            client_id: GOOGLE_CLIENT_ID,
            auto_select: false,
            callback: (resp) => {
              const p = decodeJwt(resp.credential);
              // Google has cryptographically verified the user owns this email,
              // so nobody can sign in as someone else's address.
              if (p && p.email && p.email_verified !== false) {
                onSignIn({ email: p.email, name: p.name || p.email, picture: p.picture || "" });
              }
            },
          });
          if (btnRef.current) {
            window.google.accounts.id.renderButton(btnRef.current, { theme: "outline", size: "large", width: 320, text: "continue_with", shape: "pill" });
          }
          setGReady(true);
        } else if (++tries > 50) { clearInterval(t); }
      }, 100);
      return () => clearInterval(t);
    }, []);

    const devSignIn = (p) => onSignIn({ email: p.email, name: p.name, picture: "" });
    const submitManual = () => { if (email.trim()) onSignIn({ email: email.trim(), name: email.trim(), picture: "" }); };

    return (
      <div className="auth-screen">
        <div className="auth-card">
          <div className="auth-brand"><GoogleG size={26} /></div>
          <h1 className="auth-title">Sign in</h1>
          <p className="auth-sub">Designer allocation · nove8</p>

          {GOOGLE_CLIENT_ID ? (
            <div className="auth-gbtn-wrap"><div ref={btnRef}></div>{!gReady && <div className="auth-note">Loading Google…</div>}</div>
          ) : (
            <div className="auth-dev">
              <div className="auth-dev-label"><span>Choose an account</span></div>
              <div className="auth-acct-list">
                {people.length === 0 && <div className="auth-note">No people configured yet.</div>}
                {people.map((p) => (
                  <button key={p.id} className="auth-acct" onClick={() => devSignIn(p)}>
                    <span className="auth-avatar">{initials(p.name)}</span>
                    <span className="auth-acct-meta">
                      <span className="auth-acct-name">{p.name}{p.access === "admin" && <span className="auth-tag admin">admin</span>}{p.access === "manager" && <span className="auth-tag mgr">mgr</span>}</span>
                      <span className="auth-acct-email">{p.email}</span>
                    </span>
                  </button>
                ))}
              </div>
              {manual ? (
                <div className="auth-manual">
                  <input className="auth-input" type="email" placeholder="name@nove8.com" value={email} autoFocus
                    onChange={(e) => setEmail(e.target.value)}
                    onKeyDown={(e) => { if (e.key === "Enter") submitManual(); if (e.key === "Escape") setManual(false); }} />
                  <button className="auth-btn" onClick={submitManual}>Continue</button>
                </div>
              ) : (
                <button className="auth-other" onClick={() => setManual(true)}>Use another email</button>
              )}
            </div>
          )}

          <p className="auth-foot">
            {GOOGLE_CLIENT_ID
              ? "Only emails listed in People can sign in."
              : "Dev sign-in — real Google login activates once a Client ID is set and the app is deployed. Only emails listed in People can sign in."}
          </p>
        </div>
      </div>
    );
  }

  function BlockedScreen({ email, onSignOut }) {
    return (
      <div className="auth-screen">
        <div className="auth-card">
          <div className="auth-brand denied">
            <svg width="26" height="26" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.2" strokeLinecap="round"><circle cx="12" cy="12" r="9"/><path d="M5.6 5.6l12.8 12.8"/></svg>
          </div>
          <h1 className="auth-title">No access</h1>
          <p className="auth-sub">This account isn’t on the team list.</p>
          <div className="auth-email-pill">{email}</div>
          <p className="auth-foot">Ask an admin to add <b>{email}</b> in People, then sign in again.</p>
          <button className="auth-btn ghost" onClick={onSignOut}>Use another account</button>
        </div>
      </div>
    );
  }

  function AuthGate({ children }) {
    const [auth, setAuth] = useState(loadAuth);
    const [people, setPeople] = useState(null); // null = roster still loading

    // Resolve the roster from the server (fallback: local cache) so access is
    // decided by the shared source of truth, not this device's stored copy.
    useEffect(() => {
      let alive = true;
      setPeople(null);
      fetchServerPeople().then((srv) => {
        if (!alive) return;
        setPeople((srv && srv.length) ? srv : loadPeople());
      });
      return () => { alive = false; };
    }, [auth && auth.email]);

    // Quiet background refresh so a long-open tab reflects role changes (e.g. an
    // admin demoting someone) without the person having to reload the page.
    useEffect(() => {
      const id = setInterval(() => {
        fetchServerPeople().then((srv) => { if (srv && srv.length) setPeople(srv); });
      }, 30000);
      return () => clearInterval(id);
    }, []);

    const signIn = (a) => { saveAuth(a); setAuth(a); };
    const signOut = () => {
      saveAuth(null); setAuth(null);
      if (window.google && window.google.accounts && window.google.accounts.id) {
        try { window.google.accounts.id.disableAutoSelect(); } catch (e) {}
      }
    };

    if (!auth) return <LoginScreen onSignIn={signIn} />;

    if (people === null) {
      return (
        <div className="auth-screen">
          <div className="auth-card">
            <div className="auth-brand"><GoogleG size={26} /></div>
            <h1 className="auth-title">Checking access…</h1>
            <p className="auth-sub">One moment</p>
          </div>
        </div>
      );
    }

    const person = people.find((p) => norm(p.email) === norm(auth.email)) || null;
    if (!person) return <BlockedScreen email={auth.email} onSignOut={signOut} />;

    const access = accessOf(person);
    return children({ email: auth.email, name: auth.name || person.name, picture: auth.picture || "", person, access, signOut });
  }

  window.AuthGate = AuthGate;
})();
