{% extends "forms/field.html.twig" %}

{% block label %}{% endblock %}

{% block input %}
    {% set config = grav.config %}
    {% set formId = form.id ?: form.name %}
    {% set callbackId = formId|underscorize %}
    {% set lang = grav.language.language %}

    {# Get configuration values with fallbacks #}
    {% set version = field.recaptcha_version ?? config.plugins.form.recaptcha.version ?? '2-checkbox' %}
    {% set site_key = field.recaptcha_site_key ?? config.plugins.form.recaptcha.site_key %}
    {% set theme = field.recaptcha_theme ?? config.plugins.form.recaptcha.theme ?? 'light' %}

    {% if not site_key %}
        <div class="form-error">reCAPTCHA site key is not set. Please set it in the form field or plugin configuration.</div>
    {% else %}
        {% if version == 3 or version == '3' %}
            {# --- reCAPTCHA v3 Handling --- #}
            {% set action = (page.route|trim('/') ~ '-' ~ form.name)|underscorize|md5 %}

            <div class="g-recaptcha-container"
                 data-form-id="{{ formId }}"
                 data-recaptcha-version="3"
                 data-captcha-provider="recaptcha"
                 data-intercepts-submit="true"
                 data-sitekey="{{ site_key }}"
                 data-version="3"
                 data-action="{{ action }}"
                 data-theme="{{ theme }}"
                 data-lang="{{ lang }}"
                 data-callback-id="{{ callbackId }}">
                {# Container for v3 - will be managed by JS #}
                <input type="hidden" name="data[token]" value="">
                <input type="hidden" name="data[action]" value="{{ action }}">
            </div>

            {% do assets.addJs('https://www.google.com/recaptcha/api.js?render=' ~ site_key, { group: 'bottom' }) %}

            <script>
                (function() {
                    window.GravRecaptchaInitializers = window.GravRecaptchaInitializers || {};

                    function addHiddenInput(form, name, value) {
                        const existing = form.querySelector('input[type="hidden"][name="' + name + '"]');
                        if (existing) {
                            existing.value = value;
                        } else {
                            const input = document.createElement('input');
                            input.setAttribute('type', 'hidden');
                            input.setAttribute('name', name);
                            input.setAttribute('value', value);
                            form.insertBefore(input, form.firstChild);
                        }
                    }

                    function initRecaptchaV3(container) {
                        const formId = container.dataset.formId;
                        const siteKey = container.dataset.sitekey;
                        const action = container.dataset.action;
                        const form = document.getElementById(formId);

                        if (!form) return;

                        console.log(`Initializing reCAPTCHA v3 for form ${formId}`);

                        const submitHandler = function(event) {
                            event.preventDefault();
                            console.log(`reCAPTCHA v3 intercepting submit for form ${formId}`);

                            grecaptcha.ready(function() {
                                grecaptcha.execute(siteKey, { action: action })
                                    .then(function(token) {
                                        console.log(`reCAPTCHA v3 token received for form ${formId}`);
                                        addHiddenInput(form, 'data[token]', token);
                                        addHiddenInput(form, 'data[action]', action);
                                        form.removeEventListener('submit', submitHandler);

                                        if (form.dataset.xhrEnabled === 'true' && window.GravFormXHR && typeof window.GravFormXHR.submit === 'function') {
                                            window.GravFormXHR.submit(form);
                                        } else {
                                            if (typeof form.requestSubmit === 'function') {
                                                form.requestSubmit();
                                            } else {
                                                form.submit();
                                            }
                                        }

                                        setTimeout(() => {
                                            const currentForm = document.getElementById(formId);
                                            if (currentForm && !currentForm.dataset.recaptchaListenerAttached) {
                                                currentForm.addEventListener('submit', submitHandler);
                                                currentForm.dataset.recaptchaListenerAttached = 'true';
                                            } else if (currentForm) {
                                                delete currentForm.dataset.recaptchaListenerAttached;
                                            }
                                        }, 0);
                                    });
                            });
                        };

                        delete form.dataset.recaptchaListenerAttached;
                        if (!form.dataset.recaptchaListenerAttached) {
                            form.addEventListener('submit', submitHandler);
                            form.dataset.recaptchaListenerAttached = 'true';
                        }
                    }

                    // Register the initializer function
                    const initializerFunctionName = 'initRecaptcha_{{ formId }}';
                    window.GravRecaptchaInitializers[initializerFunctionName] = function() {
                        const container = document.querySelector('[data-form-id="{{ formId }}"][data-captcha-provider="recaptcha"]');
                        if (!container) return;

                        initRecaptchaV3(container);
                    };

                    // Initial call
                    if (document.readyState === 'loading') {
                        document.addEventListener('DOMContentLoaded', window.GravRecaptchaInitializers[initializerFunctionName]);
                    } else {
                        setTimeout(window.GravRecaptchaInitializers[initializerFunctionName], 0);
                    }
                })();
            </script>

        {% elseif version == '2-invisible' %}
            {# --- reCAPTCHA v2 Invisible Handling --- #}
            <div class="g-recaptcha-container"
                 data-form-id="{{ formId }}"
                 data-recaptcha-version="2-invisible"
                 data-captcha-provider="recaptcha"
                 data-intercepts-submit="true"
                 data-sitekey="{{ site_key }}"
                 data-version="2-invisible"
                 data-theme="{{ theme }}"
                 data-lang="{{ lang }}"
                 data-callback-id="{{ callbackId }}">
                {# Container for v2 invisible - will be managed by JS #}
                <div id="g-recaptcha-{{ formId }}" class="g-recaptcha"></div>
            </div>

            <script>
                (function() {
                    window.GravRecaptchaInitializers = window.GravRecaptchaInitializers || {};

                    function addHiddenInput(form, name, value) {
                        const existing = form.querySelector('input[type="hidden"][name="' + name + '"]');
                        if (existing) {
                            existing.value = value;
                        } else {
                            const input = document.createElement('input');
                            input.setAttribute('type', 'hidden');
                            input.setAttribute('name', name);
                            input.setAttribute('value', value);
                            form.insertBefore(input, form.firstChild);
                        }
                    }

                    function initRecaptchaV2Invisible(container) {
                        const formId = container.dataset.formId;
                        const siteKey = container.dataset.sitekey;
                        const lang = container.dataset.lang;
                        const theme = container.dataset.theme;
                        const callbackId = container.dataset.callbackId || formId;
                        const form = document.getElementById(formId);
                        let widgetId = null;

                        if (!form) return;

                        console.log(`Initializing reCAPTCHA v2 Invisible for form ${formId}`);

                        const callbackName = 'captchaInvisibleOnloadCallback_' + callbackId;

                        if (typeof window[callbackName] !== 'function') {
                            window[callbackName] = function() {
                                console.log('reCAPTCHA Invisible API ready for form ' + formId);
                            };

                            if (!document.querySelector('script[src*="recaptcha/api.js?onload=' + callbackName + '"]')) {
                                const script = document.createElement('script');
                                script.src = 'https://www.google.com/recaptcha/api.js?onload=' + callbackName + '&hl=' + lang + '&theme=' + theme;
                                script.async = true;
                                script.defer = true;
                                document.head.appendChild(script);
                            }
                        }

                        const submitHandler = function(event) {
                            event.preventDefault();
                            console.log(`reCAPTCHA v2 Invisible intercepting submit for form ${formId}`);

                            if (typeof grecaptcha === 'undefined' || typeof grecaptcha.render === 'undefined') {
                                console.error('grecaptcha not ready for invisible captcha');
                                return;
                            }

                            const recaptchaId = 'g-recaptcha-' + formId;
                            let captchaElement = document.getElementById(recaptchaId);

                            if (!captchaElement) {
                                captchaElement = document.createElement('div');
                                captchaElement.setAttribute('id', recaptchaId);
                                captchaElement.className = 'g-recaptcha';
                                form.appendChild(captchaElement);
                            }

                            const renderCaptcha = () => {
                                if (widgetId !== null) {
                                    try {
                                        grecaptcha.reset(widgetId);
                                    } catch (e) {
                                        console.warn("Error resetting captcha", e);
                                    }
                                }

                                widgetId = grecaptcha.render(recaptchaId, {
                                    sitekey: siteKey,
                                    size: 'invisible',
                                    callback: function(token) {
                                        console.log(`reCAPTCHA v2 Invisible token received for form ${formId}`);
                                        addHiddenInput(form, 'g-recaptcha-response', token);
                                        form.removeEventListener('submit', submitHandler);

                                        if (form.dataset.xhrEnabled === 'true' && window.GravFormXHR && typeof window.GravFormXHR.submit === 'function') {
                                            window.GravFormXHR.submit(form);
                                        } else {
                                            if (typeof form.requestSubmit === 'function') {
                                                form.requestSubmit();
                                            } else {
                                                form.submit();
                                            }
                                        }

                                        setTimeout(() => {
                                            const currentForm = document.getElementById(formId);
                                            if (currentForm && !currentForm.dataset.recaptchaListenerAttached) {
                                                currentForm.addEventListener('submit', submitHandler);
                                                currentForm.dataset.recaptchaListenerAttached = 'true';
                                            } else if (currentForm) {
                                                delete currentForm.dataset.recaptchaListenerAttached;
                                            }
                                        }, 0);
                                    }
                                });

                                grecaptcha.execute(widgetId);
                            };

                            if (typeof grecaptcha !== 'undefined' && grecaptcha.render) {
                                renderCaptcha();
                            } else {
                                const originalOnload = window[callbackName];
                                window[callbackName] = function() {
                                    if(originalOnload) originalOnload();
                                    renderCaptcha();
                                };
                                console.warn("grecaptcha object not found immediately, waiting for onload callback: " + callbackName);
                            }
                        };

                        delete form.dataset.recaptchaListenerAttached;
                        if (!form.dataset.recaptchaListenerAttached) {
                            form.addEventListener('submit', submitHandler);
                            form.dataset.recaptchaListenerAttached = 'true';
                        }
                    }

                    // Register the initializer function
                    const initializerFunctionName = 'initRecaptcha_{{ formId }}';
                    window.GravRecaptchaInitializers[initializerFunctionName] = function() {
                        const container = document.querySelector('[data-form-id="{{ formId }}"][data-captcha-provider="recaptcha"]');
                        if (!container) return;

                        initRecaptchaV2Invisible(container);
                    };

                    // Initial call
                    if (document.readyState === 'loading') {
                        document.addEventListener('DOMContentLoaded', window.GravRecaptchaInitializers[initializerFunctionName]);
                    } else {
                        setTimeout(window.GravRecaptchaInitializers[initializerFunctionName], 0);
                    }
                })();
            </script>

        {% else %}
            {# --- reCAPTCHA v2 Checkbox Handling --- #}
            {# Add script and container #}
            {% set container_id = 'g-recaptcha-' ~ formId %}
            {% set onloadCallback = 'captchaCheckboxOnloadCallback_' ~ callbackId %}

            <div class="g-recaptcha-container"
                 data-form-id="{{ formId }}"
                 data-captcha-provider="recaptcha"
                 data-sitekey="{{ site_key }}"
                 data-version="2-checkbox"
                 data-theme="{{ theme }}"
                 data-lang="{{ lang }}"
                 data-callback-id="{{ callbackId }}">
                <div id="{{ container_id }}" class="g-recaptcha"></div>
            </div>

            {% do assets.addJs('https://www.google.com/recaptcha/api.js?onload=' ~ onloadCallback ~ '&render=explicit', { 'group': 'bottom', 'loading': 'defer' }) %}

            <script>
                (function() {
                    // Explicit rendering for reCAPTCHA v2 Checkbox
                    window.GravExplicitCaptchaInitializers = window.GravExplicitCaptchaInitializers || {};
                    const initializerFunctionName = 'initExplicitCaptcha_{{ formId }}';

                    // Define the initializer function
                    window.GravExplicitCaptchaInitializers[initializerFunctionName] = function() {
                        const containerId = '{{ container_id }}';
                        const container = document.getElementById(containerId);

                        if (!container) {
                            console.warn('reCAPTCHA container #' + containerId + ' not found.');
                            return;
                        }

                        // Prevent re-rendering if widget already exists
                        if (container.innerHTML.trim() !== '' && container.querySelector('iframe')) {
                            return;
                        }

                        // Get configuration from parent container
                        const parentContainer = container.closest('.g-recaptcha-container');
                        if (!parentContainer) {
                            console.error('Cannot find parent container for #' + containerId);
                            return;
                        }

                        const sitekey = parentContainer.dataset.sitekey;
                        const theme = parentContainer.dataset.theme;

                        if (!sitekey) {
                            console.error('reCAPTCHA sitekey missing for #' + containerId);
                            return;
                        }

                        console.log('Attempting to render reCAPTCHA in #' + containerId);

                        if (typeof grecaptcha !== 'undefined' && typeof grecaptcha.render === 'function') {
                            try {
                                grecaptcha.render(containerId, {
                                    sitekey: sitekey,
                                    theme: theme,
                                    callback: function(token) {
                                        console.log('reCAPTCHA challenge successful for #' + containerId);
                                    }
                                });
                            } catch (e) {
                                console.error('Error calling grecaptcha.render for #' + containerId, e);
                                container.innerHTML = '<p style="color:red;">Error initializing reCAPTCHA.</p>';
                            }
                        } else {
                            console.warn('grecaptcha API not available yet for #' + containerId + '. Waiting for onload.');
                        }
                    };

                    // Define the global onload callback
                    window['{{ onloadCallback }}'] = function() {
                        console.log('reCAPTCHA API loaded, triggering init for #{{ container_id }}');
                        if (window.GravExplicitCaptchaInitializers[initializerFunctionName]) {
                            window.GravExplicitCaptchaInitializers[initializerFunctionName]();
                        } else {
                            console.error("Initializer " + initializerFunctionName + " not found!");
                        }
                    };

                    // Form submit handler to check if captcha is completed
                    document.addEventListener('DOMContentLoaded', function() {
                        const form = document.getElementById('{{ formId }}');
                        if (form) {
                            form.addEventListener('submit', function(event) {
                                const response = grecaptcha.getResponse();
                                if (!response) {
                                    event.preventDefault();
                                    alert("{{ field.captcha_not_validated|t|default('Please complete the captcha')|e('js') }}");
                                } else if (form.dataset.xhrEnabled === 'true' && window.GravFormXHR && typeof window.GravFormXHR.submit === 'function') {
                                    event.preventDefault();
                                    window.GravFormXHR.submit(form);
                                }
                            });
                        }
                    });
                })();
            </script>
        {% endif %}
    {% endif %}
{% endblock %}
