import { useEffect, useRef } from 'react';

// Production Turnstile widget sitekey (overridable via VITE_TURNSTILE_SITE_KEY).
const DEFAULT_SITE_KEY = '0x4AAAAAAFJ_aTIdyaRyucCm';

declare global {
  interface Window {
    /** Injected by the SSR runtime (see src/routes/__root.tsx). */
    __PW_CONFIG__?: { graphqlUrl?: string; turnstileSiteKey?: string; siteUrl?: string };
  }
}

/**
 * Preference order: what the runtime injected (it reads the site key from the
 * backend settings, so switching keys needs no rebuild), then the build-time
 * VITE_ value, then the production default.
 */
const SITE_KEY =
  (typeof window !== 'undefined' ? window.__PW_CONFIG__?.turnstileSiteKey : undefined) ||
  (import.meta.env.VITE_TURNSTILE_SITE_KEY as string | undefined) ||
  DEFAULT_SITE_KEY;

/** Local escape hatch, next to ENABLE_TURNSTILE_BYPASS on the server. */
const DISABLED = (import.meta.env.VITE_DISABLE_TURNSTILE as string | undefined) === 'true';
const SCRIPT_SRC = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';

declare global {
  interface Window {
    turnstile?: {
      render: (
        el: HTMLElement,
        opts: {
          sitekey: string;
          action?: string;
          theme?: 'light' | 'dark' | 'auto';
          size?: 'normal' | 'compact' | 'flexible';
          callback?: (token: string) => void;
          'error-callback'?: () => void;
          'expired-callback'?: () => void;
        }
      ) => string;
      remove: (widgetId: string) => void;
      reset: (widgetId?: string) => void;
    };
  }
}

let scriptPromise: Promise<void> | null = null;
function loadScript(): Promise<void> {
  if (typeof window === 'undefined') return Promise.resolve();
  if (window.turnstile) return Promise.resolve();
  if (scriptPromise) return scriptPromise;
  scriptPromise = new Promise<void>((resolve, reject) => {
    const existing = document.querySelector<HTMLScriptElement>(`script[src^="${SCRIPT_SRC}"]`);
    if (existing) {
      existing.addEventListener('load', () => resolve());
      existing.addEventListener('error', () => reject(new Error('Failed to load Turnstile')));
      return;
    }
    const s = document.createElement('script');
    s.src = SCRIPT_SRC;
    s.async = true;
    s.defer = true;
    s.onload = () => resolve();
    s.onerror = () => reject(new Error('Failed to load Turnstile'));
    document.head.appendChild(s);
  });
  return scriptPromise;
}

interface TurnstileProps {
  onVerify: (token: string) => void;
  onExpire?: () => void;
  onError?: () => void;
  action?: string;
  theme?: 'light' | 'dark' | 'auto';
  className?: string;
}

export function Turnstile({ onVerify, onExpire, onError, action, theme = 'auto', className }: TurnstileProps) {
  const containerRef = useRef<HTMLDivElement>(null);
  const widgetIdRef = useRef<string | null>(null);

  useEffect(() => {
    if (DISABLED) {
      // The server needs ENABLE_TURNSTILE_BYPASS=true for forms to be accepted.
      // eslint-disable-next-line no-console
      console.warn('[turnstile] widget uitgeschakeld (VITE_DISABLE_TURNSTILE=true)');
      return;
    }

    let cancelled = false;
    loadScript()
      .then(() => {
        if (cancelled || !containerRef.current || !window.turnstile) return;
        widgetIdRef.current = window.turnstile.render(containerRef.current, {
          sitekey: SITE_KEY,
          ...(action ? { action } : {}),
          theme,
          size: 'flexible',
          callback: (token) => onVerify(token),
          'expired-callback': () => onExpire?.(),
          'error-callback': () => {
            // 110200 = invalid sitekey, or a domain that is not allowed for it.
            // eslint-disable-next-line no-console
            console.error(
              `[turnstile] widget kon niet laden (sitekey ${SITE_KEY.slice(0, 12)}…) — controleer de sitekey en of dit domein in Cloudflare Turnstile is toegestaan.`,
            );
            onError?.();
          },
        });
      })
      .catch((e) => {
        console.error('Turnstile load error:', e);
        onError?.();
      });
    return () => {
      cancelled = true;
      if (widgetIdRef.current && window.turnstile) {
        try { window.turnstile.remove(widgetIdRef.current); } catch { /* noop */ }
        widgetIdRef.current = null;
      }
    };
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (DISABLED) return null;

  return <div ref={containerRef} className={className} />;
}

export function resetTurnstile() {
  if (typeof window !== 'undefined' && window.turnstile) {
    try { window.turnstile.reset(); } catch { /* noop */ }
  }
}
