// Based on Cloudflare Turnstile documentation: https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/
if (!window['ddTurnstile']){
    window.ddTurnstile = (function(win, doc) {
        // change siteKey here
        var siteKey = '0x4AAAAAACB9gTR5XInxSvIi';

        var ts = new Date().getTime(),
            cbName = 'oncallBackLoadTurnstile_' + ts,
            _queue = [],
            methods = {},
            widgetId = null,
            isExecuting = false,
            isReady = false;

        function runQueue(){
            while (_queue.length>0) {
                var queue = _queue.shift();
                if (!queue || !queue.method) {
                    continue;
                }
                if (queue.method.indexOf('.') > 0) {
                    var queueSplit = queue.method.split('.');
                    if (methods[queueSplit[0]] && methods[queueSplit[0]][queueSplit[1]]) {
                        methods[queueSplit[0]][queueSplit[1]].apply(methods[queueSplit[0]], queue.arguments);
                    }
                } else {
                    if (methods[queue.method]) {
                        methods[queue.method].apply(methods, queue.arguments);
                    }
                }
            }
        }

        var containerId = 'turnstile-container-' + ts;

        function createContainer() {
            var existing = doc.getElementById(containerId);
            if (existing) return existing;

            if (!doc.body) {
                console.error('Document body not available');
                return null;
            }

            var container = doc.createElement('div');
            container.id = containerId;
            container.style.position = 'fixed';
            container.style.bottom = '20px';
            container.style.right = '20px';
            container.style.zIndex = '999999';
            container.style.opacity = '0';
            container.style.pointerEvents = 'none';
            container.style.transition = 'opacity 0.3s';
            doc.body.appendChild(container);

            return container;
        }

        // Onload callback as per documentation
        win[cbName] = function(){
            isReady = true;
            runQueue();
        }

        // Load Turnstile script with explicit rendering as per documentation
        if (typeof turnstile === "undefined"){
            (function(d, s, id) {
                var js, fjs = d.getElementsByTagName(s)[0];
                if (d.getElementById(id)) {
                    return;
                }
                js = d.createElement(s);
                js.id = id;
                // Use exact URL as per documentation: https://challenges.cloudflare.com/turnstile/v0/api.js
                // With render=explicit for explicit rendering and onload callback
                // IMPORTANT: async and defer must be false when using turnstile.ready()
                js.async = false;
                js.defer = false;
                js.src = "https://challenges.cloudflare.com/turnstile/v0/api.js?onload=" + cbName + "&render=explicit";
                js.onerror = function() {
                    console.error('Failed to load Turnstile API script');
                    isReady = false;
                };
                fjs.parentNode.insertBefore(js, fjs);
            }(doc, 'script', 'turnstile-api'));
        }

        methods.isReady = function () { 
            return isReady && typeof turnstile !== 'undefined';
        }

        // Use turnstile.ready() as per documentation for explicit rendering
        // Note: Only use turnstile.ready() if script is loaded without async/defer
        methods.onReady = function (cb) {
            if (isReady && typeof turnstile !== 'undefined') {
                // Already ready via onload callback
                if (typeof cb === 'function') {
                    cb(true);
                }
            } else if (typeof turnstile !== 'undefined' && typeof turnstile.ready === 'function') {
                // Use ready() only if turnstile is defined but not yet ready
                turnstile.ready(function() {
                    isReady = true;
                    if (typeof cb === 'function') {
                        cb(true);
                    }
                });
            } else {
                // Queue callback until ready
                _queue.push({
                    'method': 'onReady',
                    'arguments': arguments
                });
            }
        }

        methods.execute = function (action, cb) {
            // Use turnstile.ready() as per documentation for explicit rendering
            if (typeof turnstile === 'undefined' || !isReady) {
                _queue.push({
                    'method': 'execute',
                    'arguments': arguments
                });
                return;
            }

            // Prevent duplicate calls - if already executing, return early
            if (isExecuting) {
                console.warn('Turnstile execution already in progress');
                if (typeof cb === 'function') {
                    cb(''); // Return empty token for duplicate call
                }
                return;
            }

            isExecuting = true;
            var container = createContainer();
            
            if (!container) {
                isExecuting = false;
                if (typeof cb === 'function') {
                    cb(''); // Return empty token if container creation failed
                }
                return;
            }

            // If widget already exists, remove it first as per documentation
            if (widgetId !== null) {
                try {
                    turnstile.remove(widgetId);
                    widgetId = null;
                    container.innerHTML = '';
                } catch (e) {
                    // If remove fails, clear the widgetId and container
                    widgetId = null;
                    container.innerHTML = '';
                }
            }

            // Show container briefly during verification
            container.style.opacity = '1';
            container.style.pointerEvents = 'auto';

            // Render turnstile widget with timeout protection
            var renderTimeout = setTimeout(function() {
                if (isExecuting && widgetId !== null) {
                    console.warn('Turnstile render timeout - removing widget');
                    try {
                        turnstile.remove(widgetId);
                    } catch (e) {
                        // Ignore remove errors
                    }
                    widgetId = null;
                    isExecuting = false;
                    container.style.opacity = '0';
                    container.style.pointerEvents = 'none';
                    if (typeof cb === 'function') {
                        cb(''); // Return empty token on timeout
                    }
                }
            }, 30000); // 30 second timeout

            // Render widget - turnstile should already be ready since we use onload callback
            // Only use turnstile.ready() if it exists and we haven't confirmed readiness via onload
            try {
                if (typeof turnstile !== 'undefined' && typeof turnstile.ready === 'function' && !isReady) {
                    turnstile.ready(function() {
                        renderWidget();
                    });
                } else {
                    // If already ready or ready() not available, render directly
                    renderWidget();
                }
            } catch (e) {
                clearTimeout(renderTimeout);
                isExecuting = false;
                widgetId = null;
                container.style.opacity = '0';
                container.style.pointerEvents = 'none';
                console.error('Turnstile render error:', e);
                if (typeof cb === 'function') {
                    cb(''); // Return empty token on render error
                }
            }

            function renderWidget() {
                try {
                    // Render widget as per documentation: https://developers.cloudflare.com/turnstile/get-started/client-side-rendering/
                    widgetId = turnstile.render('#' + container.id, {
                        sitekey: siteKey,
                        action: action || 'submit',
                        callback: function(token) {
                            clearTimeout(renderTimeout);
                            // Hide container after getting token
                            container.style.opacity = '0';
                            container.style.pointerEvents = 'none';
                            isExecuting = false;
                            if (typeof cb === 'function') {
                                cb(token);
                            }
                        },
                        'error-callback': function(error) {
                            clearTimeout(renderTimeout);
                            container.style.opacity = '0';
                            container.style.pointerEvents = 'none';
                            turnstile.remove(widgetId);
                            isExecuting = false;
                            widgetId = null; // Clear widgetId on error
                            // Note: 404 errors from /cdn-cgi/challenge-platform/ are expected in some environments
                            // and don't necessarily mean Turnstile verification failed
                            // The error-callback is triggered for any verification issues
                            if (typeof cb === 'function') {
                                cb(''); // Return empty token on error - caller should handle this
                            }
                        },
                        'expired-callback': function() {
                            clearTimeout(renderTimeout);
                            container.style.opacity = '0';
                            container.style.pointerEvents = 'none';
                            turnstile.remove(widgetId);
                            isExecuting = false;
                            widgetId = null; // Clear widgetId on expiration
                            console.warn('Turnstile token expired');
                        },
                        theme: 'light',
                        size: 'compact'
                    });
                } catch (e) {
                    clearTimeout(renderTimeout);
                    isExecuting = false;
                    widgetId = null;
                    container.style.opacity = '0';
                    container.style.pointerEvents = 'none';
                    console.error('Turnstile render error:', e);
                    if (typeof cb === 'function') {
                        cb(''); // Return empty token on render error
                    }
                }
            }
        }

        // Reset widget as per documentation lifecycle management
        methods.reset = function() {
            if (isReady && typeof turnstile !== 'undefined' && widgetId !== null) {
                try {
                    turnstile.reset(widgetId);
                    isExecuting = false; // Clear execution flag on reset
                } catch (e) {
                    widgetId = null;
                    isExecuting = false;
                }
            }
        }

        // Get response token as per documentation
        methods.getResponse = function() {
            if (isReady && typeof turnstile !== 'undefined' && widgetId !== null) {
                try {
                    return turnstile.getResponse(widgetId);
                } catch (e) {
                    return null;
                }
            }
            return null;
        }

        // Remove widget as per documentation lifecycle management
        methods.remove = function() {
            if (isReady && typeof turnstile !== 'undefined' && widgetId !== null) {
                try {
                    turnstile.remove(widgetId);
                    widgetId = null;
                    isExecuting = false;
                } catch (e) {
                    widgetId = null;
                    isExecuting = false;
                }
            }
        }

        return methods;

    })(window, document);
}
