import { usePage } from '@inertiajs/react';
import { useEffect, useRef } from 'react';

type TurnstileApi = {
    render: (
        container: HTMLElement,
        options: {
            sitekey: string;
            theme: 'light' | 'dark';
            callback: (token: string) => void;
        },
    ) => string;
    remove: (widgetId: string) => void;
};

declare global {
    interface Window {
        turnstile?: TurnstileApi;
    }
}

let scriptPromise: Promise<void> | null = null;

function loadTurnstile(): Promise<void> {
    if (window.turnstile) {
        return Promise.resolve();
    }

    scriptPromise ??= new Promise((resolve) => {
        const existing = document.getElementById('cf-turnstile-script');

        if (existing) {
            existing.addEventListener('load', () => resolve(), { once: true });

            return;
        }

        const script = document.createElement('script');
        script.id = 'cf-turnstile-script';
        script.src = 'https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';
        script.async = true;
        script.defer = true;
        script.onload = () => resolve();
        document.head.appendChild(script);
    });

    return scriptPromise;
}

export function TurnstileField({ error, resetKey = 0, onToken }: { error?: string; resetKey?: number; onToken: (token: string) => void }) {
    const siteKey = usePage<{ turnstileSiteKey?: string | null }>().props.turnstileSiteKey;
    const container = useRef<HTMLDivElement>(null);
    const onTokenRef = useRef(onToken);
    onTokenRef.current = onToken;

    useEffect(() => {
        if (!siteKey || !container.current) {
            return;
        }

        const node = container.current;
        let widgetId = '';
        let cancelled = false;

        loadTurnstile().then(() => {
            if (cancelled || !window.turnstile || !node.isConnected) {
                return;
            }

            widgetId = window.turnstile.render(node, {
                sitekey: siteKey,
                theme: 'light',
                callback: (token) => onTokenRef.current(token),
            });
        });

        return () => {
            cancelled = true;

            if (widgetId && window.turnstile) {
                window.turnstile.remove(widgetId);
            }
        };
    }, [resetKey, siteKey]);

    if (!siteKey) {
        return null;
    }

    return (
        <div className="form-group">
            <div ref={container} />
            {error && <span className="error">{error}</span>}
        </div>
    );
}
