/* ui.jsx — shared primitives + the account/auth seam.
 *
 * Browsing is wide open (no gate at the front door). Protection lives on
 * the costly ACTIONS: account signup, Cleo apply, Request Desk submit,
 * Community post. Those call requireAuth() and carry a (mocked) Turnstile
 * token. The real bot-challenge verification + rate limits are the
 * back-end's job — here the widget and token are simulated.
 */
const { createContext, useContext, useState: useUState, useEffect: useUEffect, useRef: useURef } = React;

/* ---------- status pill ---------- */
function Pill({ kind = "mute", children }) {
  return <span className={`pill pill--${kind}`}><span className="pill__dot"/>{children}</span>;
}
/* ---------- placeholder / coming banners (dashed = "not real, on purpose") ---------- */
function Tag({ kind = "paper", children }) {
  return <span className={`tag tag--${kind}`}>{children}</span>;
}

/* ---------- mocked Turnstile widget ---------- */
function Turnstile({ onToken }) {
  const [state, setState] = useUState("checking"); // checking → ok
  useUEffect(() => {
    const stop = window.NBA.mockTurnstile((tok) => { setState("ok"); onToken && onToken(tok); });
    return stop;
  }, []);
  return (
    <div className={`turnstile turnstile--${state}`}>
      <span className="turnstile__box">
        {state === "ok"
          ? <svg width="14" height="14" viewBox="0 0 14 14"><path d="M2.5 7.5l3 3 6-7" stroke="currentColor" strokeWidth="1.8" fill="none" strokeLinecap="round" strokeLinejoin="round"/></svg>
          : <span className="turnstile__spin"/>}
      </span>
      <span className="turnstile__label">
        {state === "ok" ? "verified — you're human" : "checking you're human\u2026"}
      </span>
      <span className="turnstile__brand">bot check · mock</span>
    </div>
  );
}

/* ---------- account context ---------- */
const AccountCtx = createContext(null);
const useAccount = () => useContext(AccountCtx);

function AccountProvider({ children }) {
  const [account, setAccount] = useUState(() => window.NBA.currentAccount());
  const [auth, setAuth] = useUState(null); // { intent, onDone } | null

  // Reconcile with the real session on load — the cookie is authoritative.
  useUEffect(() => {
    if (!window.NBA.fetchMe) return;
    window.NBA.fetchMe().then((acct) => {
      if (acct) setAccount(acct);
      else if (acct === null) setAccount(null);   // undefined = network blip; leave as-is
    });
  }, []);

  const requireAuth = (intent, onDone) => {
    if (account) { onDone && onDone(account); return; }
    setAuth({ intent: intent || "do that", onDone });
  };
  const signOut = () => { window.NBA.signOut(); setAccount(null); };

  const value = { account, setAccount, requireAuth, signOut };
  return (
    <AccountCtx.Provider value={value}>
      {children}
      {auth && (
        <AuthModal intent={auth.intent}
          onClose={() => setAuth(null)}
          onAuthed={(acct) => { setAccount(acct); const cb = auth.onDone; setAuth(null); cb && cb(acct); }}/>
      )}
    </AccountCtx.Provider>
  );
}

function AuthModal({ intent, onClose, onAuthed }) {
  const btnRef = useURef(null);
  const [busy, setBusy] = useUState(false);
  const [error, setError] = useUState(null);

  const handleCredential = (response) => {
    setBusy(true); setError(null);
    window.NBA.signInWithGoogle(response.credential)
      .then((acct) => onAuthed(acct))
      .catch(() => { setBusy(false); setError("That didn't go through. Give it another try."); });
  };

  // Render Google's real Sign-In button once the GIS script is ready.
  useUEffect(() => {
    let tries = 0;
    const tryInit = () => {
      const g = window.google && window.google.accounts && window.google.accounts.id;
      if (g && btnRef.current && window.NBA.GOOGLE_CLIENT_ID) {
        g.initialize({ client_id: window.NBA.GOOGLE_CLIENT_ID, callback: handleCredential });
        g.renderButton(btnRef.current, { theme: "filled_black", size: "large", text: "signin_with", shape: "pill" });
        return;
      }
      if (tries++ < 80) setTimeout(tryInit, 100);
      else setError("Google sign-in couldn't load — check your connection and reopen this.");
    };
    tryInit();
  }, []);

  return (
    <div className="scrim" onMouseDown={(e) => { if (e.target === e.currentTarget) onClose(); }}>
      <div className="authcard nopan" role="dialog" aria-label="Sign in">
        <div className="authcard__head">
          <img src="assets/gold-paws.jpg" className="authcard__mark" alt=""/>
          <div className="col">
            <span className="authcard__title">Sign in</span>
            <span className="authcard__sub">You need an account to {intent}. Browsing stays open — this is only for actions that cost real budget.</span>
          </div>
          <button className="iconbtn" onClick={onClose} aria-label="Close">
            <svg width="14" height="14" viewBox="0 0 14 14"><path d="M3 3l8 8M11 3l-8 8" stroke="currentColor" strokeWidth="1.6" strokeLinecap="round"/></svg>
          </button>
        </div>

        <div className="authcard__google">
          <div ref={btnRef} className="gsi-real"/>
          {busy && <span className="authcard__busy">signing you in\u2026</span>}
          {error && <span className="authcard__err">{error}</span>}
        </div>

        <p className="authcard__foot">Sign-in is handled by Google — we never see your password. We keep your name, email, and avatar so the site knows who you are. Nothing else.</p>
      </div>
    </div>
  );
}

/* ---------- generic empty state ---------- */
function EmptyState({ title, body, tag, children }) {
  return (
    <div className="empty">
      {tag && <Tag kind="paper">{tag}</Tag>}
      <p className="empty__title">{title}</p>
      {body && <p className="empty__body">{body}</p>}
      {children}
    </div>
  );
}

Object.assign(window, { Pill, Tag, Turnstile, AccountProvider, useAccount, AuthModal, EmptyState });
