// captcha.jsx — Cloudflare Turnstile integration for signup + login forms.
//
// Design: we want to ship this code BEFORE the Turnstile keys exist.
//   - If window.__MASTERY_ENV__.turnstileSiteKey is empty (no key set),
//     <CaptchaWidget> renders nothing and useCaptcha() returns no token.
//     Signup / login work exactly as before. No captcha enforcement.
//   - When the site key is present, the widget renders and the user is
//     verified (usually automatically — the widget is in "managed" mode,
//     so most visitors get an invisible or one-click check and NEVER an
//     image puzzle), and the token flows into the supabase.auth.signUp /
//     signInWithPassword call via `options: { captchaToken }`.
//   - Supabase server-side captcha enforcement (provider=turnstile) is
//     toggled separately via the Management API — until that's on,
//     sending the token is a no-op. The two switches together make the
//     rollout safe.

const CAPTCHA_ENABLED = !!(window.__MASTERY_ENV__ && window.__MASTERY_ENV__.turnstileSiteKey);
const CAPTCHA_SITEKEY = (window.__MASTERY_ENV__ && window.__MASTERY_ENV__.turnstileSiteKey) || '';

// Lazy-load the Turnstile script the first time a widget mounts. We don't
// add it to index.html unconditionally so a no-key deploy doesn't ship
// the network request.
let turnstileScriptPromise = null;
function ensureTurnstileScript() {
  if (!CAPTCHA_ENABLED) return Promise.resolve(false);
  if (turnstileScriptPromise) return turnstileScriptPromise;
  turnstileScriptPromise = new Promise((resolve) => {
    if (window.turnstile) return resolve(true);
    const s = document.createElement('script');
    s.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
    s.async = true;
    s.defer = true;
    s.onload  = () => resolve(true);
    s.onerror = () => resolve(false);
    document.head.appendChild(s);
  });
  return turnstileScriptPromise;
}

// <CaptchaWidget onToken={fn} resetSignal={n} /> — renders the Turnstile
// widget if a site key is configured, otherwise renders nothing. Calls
// onToken with the token string when verified, or null when expired /
// errored / un-rendered. Bumping `resetSignal` clears the widget so the
// user gets a fresh challenge (Turnstile tokens are single-use and
// expire after ~5 minutes — replaying one fails server-side).
const CaptchaWidget = ({ onToken, theme = 'light', resetSignal = 0 }) => {
  const containerRef = React.useRef(null);
  const widgetIdRef  = React.useRef(null);

  React.useEffect(() => {
    if (!CAPTCHA_ENABLED) return;
    let cancelled = false;
    ensureTurnstileScript().then((ok) => {
      if (!ok || cancelled || !containerRef.current || !window.turnstile) return;
      try {
        widgetIdRef.current = window.turnstile.render(containerRef.current, {
          sitekey:    CAPTCHA_SITEKEY,
          theme,
          callback:    (token) => onToken && onToken(token),
          'expired-callback': () => onToken && onToken(null),
          'error-callback':   () => onToken && onToken(null),
        });
      } catch (e) {
        // already rendered into this node — ignore.
      }
    });
    return () => { cancelled = true; };
  }, [onToken, theme]);

  // When the caller bumps resetSignal, blank the widget + the token so
  // the next submit demands a fresh challenge.
  React.useEffect(() => {
    if (!CAPTCHA_ENABLED || resetSignal === 0) return;
    if (window.turnstile && widgetIdRef.current != null) {
      try { window.turnstile.reset(widgetIdRef.current); } catch (e) {}
    }
    onToken && onToken(null);
  }, [resetSignal]);

  if (!CAPTCHA_ENABLED) return null;
  return (
    <div style={{ margin: '12px 0' }}>
      <div ref={containerRef} />
    </div>
  );
};

// useCaptcha() — hook that returns { token, widget, required, reset, enabled }.
//   - widget is a React element you drop into the form.
//   - token is the current verified token (or null).
//   - required is true when captcha is enabled and a token hasn't been
//     captured yet — guard the submit button with it.
//   - reset() clears the widget. Call it inside the submit handler AFTER
//     using the token (success or error) so the next attempt always
//     uses a fresh challenge — Turnstile tokens are single-use and
//     reusing one is rejected server-side.
function useCaptcha() {
  const [token, setToken] = React.useState(null);
  const [resetSignal, setResetSignal] = React.useState(0);
  const widget = React.createElement(CaptchaWidget, { onToken: setToken, resetSignal });
  const reset = React.useCallback(() => {
    setToken(null);
    setResetSignal(s => s + 1);
  }, []);
  return { token, widget, required: CAPTCHA_ENABLED && !token, reset, enabled: CAPTCHA_ENABLED };
}

Object.assign(window, { CaptchaWidget, useCaptcha, CAPTCHA_ENABLED });
