/**
 * AnchorKit Elementor Editor JavaScript
 * 
 * Handles live preview updates for TOC widget settings in Elementor editor
 */

(function ($) {
    'use strict';

    const anchorkitDebugLog = (...args) => {
        if (!window || !window.anchorkitDebug) {
            return;
        }

        if (window.console && typeof window.console.log === 'function') {
            window.console.log(...args);
        }
    };

    let resetHandlersBound = false;
    let cachedResetConfig = null;

    function getResetConfig() {
        if (cachedResetConfig && typeof cachedResetConfig === 'object') {
            return cachedResetConfig;
        }

        if (window.anchorkitElementorResetConfig && typeof window.anchorkitElementorResetConfig === 'object') {
            cachedResetConfig = window.anchorkitElementorResetConfig;
            return cachedResetConfig;
        }

        return null;
    }

    function cloneValue(value) {
        if (value === null || value === undefined) {
            return value;
        }

        if (Array.isArray(value)) {
            return value.map(cloneValue);
        }

        if (typeof value === 'object') {
            try {
                return JSON.parse(JSON.stringify(value));
            } catch (error) {
                const copy = {};
                Object.keys(value).forEach(function (key) {
                    copy[key] = cloneValue(value[key]);
                });
                return copy;
            }
        }

        return value;
    }

    function getActiveAnchorKitModel() {
        if (typeof elementor === 'undefined') {
            return null;
        }

        // Method 1: Try elementor.getCurrentElement() (Elementor 3.x+)
        if (typeof elementor.getCurrentElement === 'function') {
            const current = elementor.getCurrentElement();
            if (current && current.model && current.model.get && current.model.get('widgetType') === 'anchorkit-toc') {
                return current.model;
            }
        }

        // Method 2: Get from panel's current view (most reliable for editor context)
        if (elementor.panel && elementor.panel.currentView && typeof elementor.panel.currentView.getOption === 'function') {
            const editedView = elementor.panel.currentView.getOption('editedElementView');
            if (editedView && editedView.model && editedView.model.get('widgetType') === 'anchorkit-toc') {
                return editedView.model;
            }
        }

        // Method 3: Check for selection manager (Elementor 3.7+)
        if (elementor.selection && typeof elementor.selection.getElements === 'function') {
            const selectedElements = elementor.selection.getElements();
            if (selectedElements && selectedElements.length === 1) {
                const selectedModel = selectedElements[0].model || selectedElements[0];
                if (selectedModel && selectedModel.get && selectedModel.get('widgetType') === 'anchorkit-toc') {
                    return selectedModel;
                }
            }
        }

        // Method 4: Look for the active element in the DOM and get its model
        const $activeElement = $('.elementor-element.elementor-element-edit-mode');
        if ($activeElement.length && typeof elementorFrontend !== 'undefined' && elementorFrontend.config && elementorFrontend.config.elements) {
            const elementId = $activeElement.data('id');
            if (elementId) {
                const model = elementorFrontend.config.elements.$elements.get(elementId);
                if (model && model.get('widgetType') === 'anchorkit-toc') {
                    return model;
                }
            }
        }

        return null;
    }

    function updatePanelControlInput(controlId, value) {
        if (typeof elementor === 'undefined' || !elementor.panel || !elementor.panel.currentView) {
            return;
        }

        var currentPageView = elementor.panel.currentView.currentPageView;
        if (!currentPageView || !currentPageView.$el) {
            return;
        }

        var $panel = currentPageView.$el;
        var selector = '[data-setting="' + controlId + '"]';
        var $input = $panel.find(selector);

        if (!$input.length) {
            return;
        }

        var stringValue = (value === null || typeof value === 'undefined') ? '' : String(value);

        if ($input.attr('type') === 'checkbox' || $input.attr('role') === 'switch') {
            var shouldCheck = stringValue === 'yes' || stringValue === 'true' || stringValue === '1';
            if ($input.prop('checked') !== shouldCheck) {
                $input.prop('checked', shouldCheck).trigger('input').trigger('change');
            }
            return;
        }

        if ($input.is('select')) {
            if ($input.val() !== stringValue) {
                $input.val(stringValue).trigger('input').trigger('change');
            }
            return;
        }

        if ($input.val() !== stringValue) {
            $input.val(stringValue).trigger('input').trigger('change');
        }
    }

    /**
     * Sync design_editor_mode when theme changes
     * Only syncs when theme is explicitly light or dark (not system)
     */
    function syncEditorModeFromTheme(themeValue, model) {
        if (themeValue === 'light' || themeValue === 'dark') {
            var currentEditorMode = typeof model.getSetting === 'function'
                ? model.getSetting('design_editor_mode')
                : null;
            if (currentEditorMode !== themeValue) {
                anchorkitDebugLog('[AnchorKit] Syncing design_editor_mode to match theme:', themeValue);
                if (typeof model.setSetting === 'function') {
                    model.setSetting('design_editor_mode', themeValue);
                }
                updatePanelControlInput('design_editor_mode', themeValue);
            }
        }
    }

    /**
     * Sync theme when design_editor_mode changes
     * Does not override 'system' theme setting
     */
    function syncThemeFromEditorMode(editorModeValue, model) {
        var currentTheme = typeof model.getSetting === 'function'
            ? model.getSetting('theme')
            : null;
        // Only sync if current theme is not 'system' and doesn't already match
        if (currentTheme !== 'system' && currentTheme !== editorModeValue) {
            anchorkitDebugLog('[AnchorKit] Syncing theme to match design_editor_mode:', editorModeValue);
            if (typeof model.setSetting === 'function') {
                model.setSetting('theme', editorModeValue);
            }
            updatePanelControlInput('theme', editorModeValue);
        }
    }

    function showResetMessage(message, isWarning) {
        if (!message) {
            return;
        }

        if (window.elementorCommon && elementorCommon.notifications && typeof elementorCommon.notifications.showToast === 'function') {
            elementorCommon.notifications.showToast({
                message: message,
                type: isWarning ? 'warning' : 'success',
                duration: 3500,
            });
            return;
        }

        if (window.elementor && elementor.notifications && typeof elementor.notifications.showToast === 'function') {
            elementor.notifications.showToast({ message: message });
            return;
        }

        if (isWarning) {
            console.warn(message);
        } else {
            console.info(message);
        }
    }

    function applyResetValues(model, controls) {
        if (!model || !controls) {
            console.warn('[AnchorKit Reset] Invalid model or controls:', { model: !!model, controls: !!controls });
            return false;
        }

        // Get the settings model - in Elementor, settings are stored in a nested Backbone Model
        const settingsModel = (typeof model.get === 'function') ? model.get('settings') : null;

        if (!settingsModel && typeof model.setSetting !== 'function') {
            console.warn('[AnchorKit Reset] Could not get settings model from widget');
            return false;
        }

        // Batch the changes to avoid multiple renders
        const controlIds = Object.keys(controls);
        const settingsToApply = {};

        controlIds.forEach(function (controlId) {
            settingsToApply[controlId] = cloneValue(controls[controlId]);
        });

        anchorkitDebugLog('[AnchorKit Reset] Applying settings:', Object.keys(settingsToApply).length, 'controls');

        // Apply settings one by one to ensure each triggers proper change events
        Object.keys(settingsToApply).forEach(function (controlId) {
            const value = settingsToApply[controlId];

            anchorkitDebugLog('[AnchorKit Reset] Setting', controlId, '=', value);

            let wasSet = false;

            if (typeof model.setSetting === 'function') {
                model.setSetting(controlId, value);
                wasSet = true;
            }

            if (!wasSet && settingsModel && typeof settingsModel.set === 'function') {
                settingsModel.set(controlId, value);
                wasSet = true;
            }

            if (wasSet) {
                const newValue = typeof model.getSetting === 'function'
                    ? model.getSetting(controlId)
                    : (settingsModel && typeof settingsModel.get === 'function'
                        ? settingsModel.get(controlId)
                        : null);
                anchorkitDebugLog('[AnchorKit Reset] Verified', controlId, '=', newValue);
                updatePanelControlInput(controlId, value);
            } else {
                console.warn('[AnchorKit Reset] Unable to set control', controlId);
            }
        });

        // Mark the document as changed so Elementor knows to save
        if (typeof elementor !== 'undefined' && elementor.saver) {
            elementor.saver.setFlagEditorChange(true);
        }

        // Force Elementor to regenerate the widget's view and CSS
        setTimeout(function () {
            try {
                // Method 1: Use Elementor's internal rendering
                if (model.renderRemoteServer) {
                    model.renderRemoteServer();
                }

                // Method 2: Trigger the element's own render
                if (model.view && typeof model.view.renderUI === 'function') {
                    model.view.renderUI();
                } else if (model.view && typeof model.view.render === 'function') {
                    model.view.render();
                }

                // Note: We don't call currentPageView.render() here because it breaks
                // Elementor's tab switching functionality. Elementor automatically updates
                // the panel controls when settings change via setSetting() and updatePanelControlInput()

                anchorkitDebugLog('[AnchorKit Reset] Widget render triggered');
            } catch (e) {
                console.warn('[AnchorKit Reset] Render error:', e);
            }
        }, 100);

        return true;
    }

    function initAnchorKitResetButtons() {
        if (resetHandlersBound) {
            anchorkitDebugLog('[AnchorKit] Reset handlers already bound');
            return;
        }

        const config = getResetConfig();
        if (!config) {
            anchorkitDebugLog('[AnchorKit] Reset config not yet available, retrying...');
            // Retry shortly in case localization hasn't loaded yet
            setTimeout(initAnchorKitResetButtons, 500);
            return;
        }

        anchorkitDebugLog('[AnchorKit] Reset config loaded, binding handlers. Sections:', Object.keys(config.sections || {}));
        resetHandlersBound = true;

        // Bind to multiple containers to handle Elementor's panel structure
        // The panel content is dynamically loaded, so we use delegation
        var containers = [
            document,
            '#elementor-panel',
            '#elementor-panel-content-wrapper',
            '.elementor-panel-content-wrapper'
        ];

        var bindTarget = $(document);

        // Try to find Elementor's panel container
        if ($('#elementor-panel').length) {
            bindTarget = $('#elementor-panel');
            anchorkitDebugLog('[AnchorKit] Binding to #elementor-panel');
        }

        // Use event delegation to catch dynamically added buttons
        bindTarget.on('click.anchorkit', '.anchorkit-el-reset-button', function (event) {
            event.preventDefault();
            event.stopPropagation();

            anchorkitDebugLog('[AnchorKit] Reset button clicked');

            const $button = $(this);
            if ($button.prop('disabled')) {
                anchorkitDebugLog('[AnchorKit] Button is disabled, ignoring');
                return;
            }

            const target = $button.data('resetTarget') || $button.attr('data-reset-target');
            anchorkitDebugLog('[AnchorKit] Reset target:', target);

            if (!target) {
                console.warn('[AnchorKit] No reset target found on button');
                return;
            }

            const runtimeConfig = getResetConfig();
            if (!runtimeConfig) {
                console.warn('[AnchorKit] Runtime config not available');
                return;
            }

            const sections = runtimeConfig.sections || {};
            const strings = runtimeConfig.strings || {};
            const label = $button.data('resetLabel') || $button.attr('data-reset-label') || '';

            anchorkitDebugLog('[AnchorKit] Looking for controls. Target:', target, 'Available sections:', Object.keys(sections));

            const controls = target === 'all'
                ? runtimeConfig.all_controls
                : (sections[target] ? sections[target].controls : null);

            if (!controls) {
                console.warn('[AnchorKit] No controls found for target:', target);
                return;
            }

            anchorkitDebugLog('[AnchorKit] Found', Object.keys(controls).length, 'controls to reset');

            const confirmMessage = target === 'all'
                ? (strings.allConfirm || 'Reset all settings to defaults?')
                : ((strings.sectionConfirm || 'Reset %s settings to defaults?').replace('%s', label));

            if (confirmMessage && !window.confirm(confirmMessage)) {
                anchorkitDebugLog('[AnchorKit] User cancelled reset');
                return;
            }

            const model = getActiveAnchorKitModel();
            anchorkitDebugLog('[AnchorKit] Active model:', model ? 'found' : 'not found');

            if (!model) {
                showResetMessage(strings.noWidget || 'Open the AnchorKit widget panel before resetting.', true);
                return;
            }

            $button.prop('disabled', true).attr('aria-disabled', 'true');

            const success = applyResetValues(model, controls);

            if (success) {
                const successMessage = target === 'all'
                    ? (strings.allSuccess || 'Widget reset to defaults.')
                    : ((strings.sectionSuccess || '%s settings reset to defaults.').replace('%s', label));
                if (successMessage) {
                    showResetMessage(successMessage, false);
                }
            } else {
                showResetMessage('Failed to reset settings. Check browser console for details.', true);
            }

            setTimeout(function () {
                $button.prop('disabled', false).attr('aria-disabled', 'false');
            }, 400);
        });
    }

    /**
     * Update TOC container inline styles based on widget settings
     */
    function updateTocStyles(elementModel) {
        if (!elementModel) {
            return;
        }

        // Get the widget element - IMPORTANT: Elementor preview is in an iframe!
        const elementId = elementModel.get('id');
        
        // Try to find widget in the Elementor preview iframe first
        let $widget = $();
        let $previewDocument = null;
        
        // Method 1: Use elementor.$preview (the iframe jQuery object)
        if (typeof elementor !== 'undefined' && elementor.$preview && elementor.$preview.length) {
            try {
                $previewDocument = elementor.$preview.contents();
                $widget = $previewDocument.find('.elementor-element-' + elementId);
            } catch (e) {
                // Cross-origin or other error
            }
        }
        
        // Method 2: Try finding the iframe directly
        if (!$widget.length) {
            const $iframe = $('#elementor-preview-iframe');
            if ($iframe.length) {
                try {
                    $previewDocument = $iframe.contents();
                    $widget = $previewDocument.find('.elementor-element-' + elementId);
                } catch (e) {
                    // Cross-origin error
                }
            }
        }
        
        // Method 3: Fallback to current document (for frontend preview)
        if (!$widget.length) {
            $widget = $('.elementor-element-' + elementId);
        }
        
        if (!$widget.length) {
            return;
        }

        const $tocContainer = $widget.find('.anchorkit-toc-container');
        
        if ($tocContainer.length === 0) {
            return;
        }

        // Get settings from model - settings is a Backbone Model in Elementor
        const settingsModel = elementModel.get('settings');
        if (!settingsModel) {
            return;
        }

        // Get width settings - use .get() for Backbone Model or direct access for plain objects
        const getSetting = function (key) {
            if (typeof settingsModel.get === 'function') {
                return settingsModel.get(key);
            }
            return settingsModel[key];
        };

        const tocWidth = getSetting('toc_width');
        const alignment = getSetting('alignment');
        const sticky = getSetting('sticky');
        const stickyPosition = getSetting('sticky_position');
        const advancedTypographyOverride = getSetting('advanced_typography_override');

        // Don't apply width styles if sticky is enabled with left/right position
        const isStickySidebar = sticky === 'yes' && (stickyPosition === 'left' || stickyPosition === 'right');

        if (!isStickySidebar) {
            const tocElement = $tocContainer[0];
            if (!tocElement) {
                return;
            }

            // Apply width percentage
            if (tocWidth) {
                let widthValue = '';
                if (typeof tocWidth === 'object' && tocWidth.size !== undefined) {
                    widthValue = tocWidth.size + (tocWidth.unit || '%');
                } else if (typeof tocWidth === 'number') {
                    widthValue = tocWidth + '%';
                } else if (typeof tocWidth === 'string') {
                    widthValue = tocWidth;
                }
                if (widthValue) {
                    tocElement.style.setProperty('width', widthValue, 'important');
                }
            }

            // Apply alignment margins
            if (alignment === 'left') {
                tocElement.style.setProperty('margin', '20px auto 20px 0', 'important');
            } else if (alignment === 'right') {
                tocElement.style.setProperty('margin', '20px 0 20px auto', 'important');
            } else {
                tocElement.style.setProperty('margin', '20px auto', 'important');
            }
        }

        // Update font sizes if advanced typography override is enabled
        if (advancedTypographyOverride === 'yes') {
            const getFontSize = function (setting) {
                if (!setting) return null;
                if (typeof setting === 'object' && setting.size !== undefined) {
                    return setting.size;
                }
                if (typeof setting === 'number') {
                    return setting;
                }
                return null;
            };

            const titleFontSize = getFontSize(getSetting('title_font_size'));
            const h2FontSize = getFontSize(getSetting('h2_font_size'));
            const h3FontSize = getFontSize(getSetting('h3_font_size'));
            const h4FontSize = getFontSize(getSetting('h4_font_size'));
            const h5FontSize = getFontSize(getSetting('h5_font_size'));
            const h6FontSize = getFontSize(getSetting('h6_font_size'));

            // Get the TOC instance ID from the container
            const tocInstanceId = $tocContainer.attr('id') || $tocContainer.attr('data-anchorkit-instance');
            
            if (tocInstanceId) {
                // Update title font size
                if (titleFontSize) {
                    const $title = $tocContainer.find('.anchorkit-toc-title');
                    $title.css('font-size', titleFontSize + 'px');
                }

                // Update heading level font sizes
                if (h2FontSize) {
                    const $h2Links = $tocContainer.find('.anchorkit-toc-heading-level-2 > .anchorkit-toc-link');
                    $h2Links.css('font-size', h2FontSize + 'px');
                }
                if (h3FontSize) {
                    $tocContainer.find('.anchorkit-toc-heading-level-3 > .anchorkit-toc-link').css('font-size', h3FontSize + 'px');
                }
                if (h4FontSize) {
                    $tocContainer.find('.anchorkit-toc-heading-level-4 > .anchorkit-toc-link').css('font-size', h4FontSize + 'px');
                }
                if (h5FontSize) {
                    $tocContainer.find('.anchorkit-toc-heading-level-5 > .anchorkit-toc-link').css('font-size', h5FontSize + 'px');
                }
                if (h6FontSize) {
                    $tocContainer.find('.anchorkit-toc-heading-level-6 > .anchorkit-toc-link').css('font-size', h6FontSize + 'px');
                }
            }
        }
    }

    /**
     * Helper function to read font sizes from model and apply them to preview
     * This is used by the polling mechanism to apply font sizes live
     */
    function applyFontSizesFromPanel(model) {
        if (!model) return;
        
        const elementId = model.get('id');
        
        // Find widget in preview iframe
        let $widget = $();
        if (typeof elementor !== 'undefined' && elementor.$preview && elementor.$preview.length) {
            try {
                $widget = elementor.$preview.contents().find('.elementor-element-' + elementId);
            } catch (e) {}
        }
        if (!$widget.length) {
            const $iframe = $('#elementor-preview-iframe');
            if ($iframe.length) {
                try {
                    $widget = $iframe.contents().find('.elementor-element-' + elementId);
                } catch (e) {}
            }
        }
        
        if (!$widget.length) return;
        
        const $tocContainer = $widget.find('.anchorkit-toc-container');
        if (!$tocContainer.length) return;
        
        // Get settings from model
        const settings = model.get('settings');
        const getSetting = function(key) {
            if (typeof settings.get === 'function') {
                return settings.get(key);
            }
            return settings[key];
        };
        
        const overrideEnabled = getSetting('advanced_typography_override') === 'yes';
        
        if (!overrideEnabled) return;
        
        // Extract font sizes from model (SLIDER returns {unit: 'px', size: number})
        const getFontSize = function(setting) {
            if (!setting) return null;
            if (typeof setting === 'object' && setting.size !== undefined) {
                return parseFloat(setting.size);
            }
            if (typeof setting === 'number') {
                return setting;
            }
            return null;
        };
        
        const titleFontSize = getFontSize(getSetting('title_font_size'));
        const h2FontSize = getFontSize(getSetting('h2_font_size'));
        const h3FontSize = getFontSize(getSetting('h3_font_size'));
        const h4FontSize = getFontSize(getSetting('h4_font_size'));
        const h5FontSize = getFontSize(getSetting('h5_font_size'));
        const h6FontSize = getFontSize(getSetting('h6_font_size'));
        
        // Apply font sizes directly to preview elements using setProperty for !important
        if (titleFontSize !== null) {
            $tocContainer.find('.anchorkit-toc-title').each(function() {
                this.style.setProperty('font-size', titleFontSize + 'px', 'important');
            });
        }
        if (h2FontSize !== null) {
            $tocContainer.find('.anchorkit-toc-heading-level-2 > .anchorkit-toc-link').each(function() {
                this.style.setProperty('font-size', h2FontSize + 'px', 'important');
            });
        }
        if (h3FontSize !== null) {
            $tocContainer.find('.anchorkit-toc-heading-level-3 > .anchorkit-toc-link').each(function() {
                this.style.setProperty('font-size', h3FontSize + 'px', 'important');
            });
        }
        if (h4FontSize !== null) {
            $tocContainer.find('.anchorkit-toc-heading-level-4 > .anchorkit-toc-link').each(function() {
                this.style.setProperty('font-size', h4FontSize + 'px', 'important');
            });
        }
        if (h5FontSize !== null) {
            $tocContainer.find('.anchorkit-toc-heading-level-5 > .anchorkit-toc-link').each(function() {
                this.style.setProperty('font-size', h5FontSize + 'px', 'important');
            });
        }
        if (h6FontSize !== null) {
            $tocContainer.find('.anchorkit-toc-heading-level-6 > .anchorkit-toc-link').each(function() {
                this.style.setProperty('font-size', h6FontSize + 'px', 'important');
            });
        }
    }

    /**
     * Initialize Elementor editor hooks
     */
    function initElementorEditor() {
        if (typeof elementor === 'undefined' || !elementor.on) {
            return;
        }

        // Store polling intervals by model ID to prevent leaks (module-level)
        if (typeof window.anchorkitFontSizePollIntervals === 'undefined') {
            window.anchorkitFontSizePollIntervals = {};
        }
        const fontSizePollIntervals = window.anchorkitFontSizePollIntervals;
        
        // Register close handler once globally to clean up all intervals
        if (!window.anchorkitCloseHandlerRegistered) {
            elementor.hooks.addAction('panel/close', function() {
                // Clear all polling intervals when panel closes
                Object.keys(fontSizePollIntervals).forEach(function(elementId) {
                    if (fontSizePollIntervals[elementId]) {
                        clearInterval(fontSizePollIntervals[elementId]);
                        delete fontSizePollIntervals[elementId];
                    }
                });
            });
            window.anchorkitCloseHandlerRegistered = true;
        }

        // Listen for widget settings changes
        elementor.hooks.addAction('panel/open_editor/widget/anchorkit-toc', function (panel, model, view) {
            if (!model) {
                return;
            }

            // Update styles when widget panel opens
            setTimeout(function () {
                updateTocStyles(model);
            }, 100);

            // Store previous font size values to detect changes
            let previousFontSizes = {};
            const getCurrentFontSizes = function() {
                const settings = model.get('settings');
                const getSetting = function(key) {
                    if (typeof settings.get === 'function') {
                        return settings.get(key);
                    }
                    return settings[key];
                };
                return {
                    override: getSetting('advanced_typography_override'),
                    title: getSetting('title_font_size'),
                    h2: getSetting('h2_font_size'),
                    h3: getSetting('h3_font_size'),
                    h4: getSetting('h4_font_size'),
                    h5: getSetting('h5_font_size'),
                    h6: getSetting('h6_font_size')
                };
            };
            
            // Clear any existing interval for this model
            const elementId = model.get('id');
            if (elementId && fontSizePollIntervals[elementId]) {
                clearInterval(fontSizePollIntervals[elementId]);
                delete fontSizePollIntervals[elementId];
            }
            
            // Poll for font size changes when panel is open (SLIDER controls don't always fire change:settings)
            const fontSizePollInterval = setInterval(function() {
                const current = getCurrentFontSizes();
                const changed = 
                    JSON.stringify(current.override) !== JSON.stringify(previousFontSizes.override) ||
                    JSON.stringify(current.title) !== JSON.stringify(previousFontSizes.title) ||
                    JSON.stringify(current.h2) !== JSON.stringify(previousFontSizes.h2) ||
                    JSON.stringify(current.h3) !== JSON.stringify(previousFontSizes.h3) ||
                    JSON.stringify(current.h4) !== JSON.stringify(previousFontSizes.h4) ||
                    JSON.stringify(current.h5) !== JSON.stringify(previousFontSizes.h5) ||
                    JSON.stringify(current.h6) !== JSON.stringify(previousFontSizes.h6);
                
                if (changed) {
                    previousFontSizes = JSON.parse(JSON.stringify(current));
                    
                    // Apply font sizes immediately
                    applyFontSizesFromPanel(model);
                }
            }, 100); // Check every 100ms
            
            // Store interval ID for cleanup
            if (elementId) {
                fontSizePollIntervals[elementId] = fontSizePollInterval;
            }

            // Listen for settings changes
            model.on('change:settings', function (changedModel, options) {
                const changed = options.changed || {};

                // Sync theme <-> design_editor_mode bidirectionally
                if ('theme' in changed) {
                    syncEditorModeFromTheme(changed.theme, changedModel);
                }
                if ('design_editor_mode' in changed) {
                    syncThemeFromEditorMode(changed.design_editor_mode, changedModel);
                }

                // Check if ACF field names or merge mode changed - this requires widget re-render
                if ('acf_field_names' in changed || 'acf_enabled' in changed || 'acf_merge_mode' in changed) {
                    // Force Elementor to refresh the widget preview when ACF settings change
                    // This ensures the TOC updates with new/excluded ACF content
                    setTimeout(function () {
                        // Use Elementor's refresh mechanism
                        if (typeof elementor !== 'undefined') {
                            // Trigger element refresh
                            const elementId = changedModel.get('id');
                            if (elementId) {
                                // Force preview refresh for this element
                                elementor.channels.editor.on('element:refresh', function () {
                                    // Widget will refresh
                                });
                                // Trigger refresh
                                elementor.channels.editor.trigger('element:refresh', {
                                    id: elementId
                                });
                            }
                        }
                    }, 200);
                }

                // Check if any width-related settings changed
                if ('toc_width' in changed ||
                    'alignment' in changed ||
                    'sticky' in changed ||
                    'sticky_position' in changed) {

                    // Update styles immediately
                    setTimeout(function () {
                        updateTocStyles(changedModel);
                    }, 10);
                }

                // Check if advanced typography font sizes changed
                const fontSizeChanged = 'advanced_typography_override' in changed ||
                    'title_font_size' in changed ||
                    'h2_font_size' in changed ||
                    'h3_font_size' in changed ||
                    'h4_font_size' in changed ||
                    'h5_font_size' in changed ||
                    'h6_font_size' in changed ||
                    'line_height' in changed ||
                    'letter_spacing' in changed ||
                    'text_transform' in changed ||
                    'link_underline' in changed;

                if (fontSizeChanged) {
                    // Update font sizes immediately for live preview
                    setTimeout(function () {
                        updateTocStyles(changedModel);
                    }, 10);
                    
                    // Also trigger widget refresh to ensure inline CSS is regenerated
                    // This is needed for proper persistence and full re-render
                    setTimeout(function () {
                        if (typeof elementor !== 'undefined') {
                            const elementId = changedModel.get('id');
                            if (elementId) {
                                // Trigger refresh to re-render widget with new font sizes
                                elementor.channels.editor.trigger('element:refresh', {
                                    id: elementId
                                });
                            }
                        }
                    }, 200);
                }
            });
        });

        // Also listen for general panel changes
        elementor.on('panel:change', function (panel, view, settings) {
            if (!view || !view.model) {
                return;
            }

            const widgetType = view.model.get('widgetType');
            if (widgetType === 'anchorkit-toc') {
                // Check if ACF settings changed - requires full widget refresh
                if (settings && ('acf_field_names' in settings || 'acf_enabled' in settings || 'acf_merge_mode' in settings)) {
                    // ACF content changes require widget re-render, not just style update
                    // Elementor should handle this automatically, but we can force it
                    setTimeout(function () {
                        // Trigger element refresh to update TOC content
                        if (view.model && view.model.view) {
                            view.model.view.render();
                        }
                    }, 300);
                }

                // Check if width-related settings changed
                if (settings && (
                    'toc_width' in settings ||
                    'alignment' in settings ||
                    'sticky' in settings ||
                    'sticky_position' in settings
                )) {
                    setTimeout(function () {
                        updateTocStyles(view.model);
                    }, 10);
                }
            }
        });

        // Update styles when widget is rendered/refreshed
        elementor.hooks.addAction('frontend/element_ready/anchorkit-toc.default', function ($scope) {
            if (!$scope || !$scope.length) {
                return;
            }

            const $widget = $scope.closest('.elementor-element');
            if (!$widget.length) {
                return;
            }

            const elementId = $widget.data('id');
            if (!elementId) {
                return;
            }

            // Get element model from Elementor
            const elementModel = elementorFrontend.config.elements.$elements.get(elementId);
            if (elementModel) {
                setTimeout(function () {
                    updateTocStyles(elementModel);
                }, 100);
            }
        });
    }

    // Direct approach: Listen to input changes in Elementor panel
    function setupDirectControlListeners() {
        // Listen for input changes on width-related controls
        $(document).on('input change', '.elementor-control-toc_width input, .elementor-control-alignment select', function () {
            // Find the currently edited element
            const $activeElement = $('.elementor-element.elementor-element-edit-mode');
            if ($activeElement.length) {
                const elementId = $activeElement.data('id');
                if (elementId && typeof elementorFrontend !== 'undefined' && elementorFrontend.config && elementorFrontend.config.elements) {
                    const elementModel = elementorFrontend.config.elements.$elements.get(elementId);
                    if (elementModel) {
                        setTimeout(function () {
                            updateTocStyles(elementModel);
                        }, 50);
                    }
                }
            }
        });

        // Listen for font size slider changes - these don't trigger model.on('change:settings')
        // Use broad selector to catch all inputs in font size controls, then filter
        // Also listen on the Elementor panel directly since inputs may be in shadow DOM or iframes
        
        // Broad listener for ANY input in typography-related controls
        $(document).on('input change mouseup', '#elementor-panel input, #elementor-panel-content-wrapper input', function () {
            const $this = $(this);
            const $control = $this.closest('[class*="elementor-control"]');
            const controlClass = $control.attr('class') || '';
            
            // Check if this is a font size related control
            const isFontSizeControl = controlClass.includes('title_font_size') ||
                controlClass.includes('h2_font_size') ||
                controlClass.includes('h3_font_size') ||
                controlClass.includes('h4_font_size') ||
                controlClass.includes('h5_font_size') ||
                controlClass.includes('h6_font_size') ||
                controlClass.includes('advanced_typography_override');
            
            if (isFontSizeControl) {
                // Get the active AnchorKit widget model
                const model = getActiveAnchorKitModel();
                if (model) {
                    // Read the latest value directly from all slider inputs and apply immediately
                    applyFontSizesFromPanel(model);
                }
            }
        });

        // Listen for theme control changes (SELECT) to sync with design_editor_mode
        $(document).on('change', '.elementor-control-theme select[data-setting="theme"]', function () {
            const newTheme = $(this).val();
            const model = getActiveAnchorKitModel();
            if (model && (newTheme === 'light' || newTheme === 'dark')) {
                syncEditorModeFromTheme(newTheme, model);
            }
        });

        // Listen for design_editor_mode control changes (CHOOSE radio inputs) to sync with theme
        $(document).on('change', '.elementor-control-design_editor_mode input[type="radio"]', function () {
            if (!$(this).is(':checked')) return;
            const newEditorMode = $(this).val();
            const model = getActiveAnchorKitModel();
            if (model) {
                syncThemeFromEditorMode(newEditorMode, model);
            }
        });

        // Listen for ACF field names and merge mode changes - requires widget refresh
        let acfFieldNamesTimeout;
        $(document).on('input change blur', '.elementor-control-acf_field_names textarea, .elementor-control-acf_field_names input, .elementor-control-acf_merge_mode select', function () {
            const $this = $(this);
            const value = $this.val();
            const isAcfFieldNames = $this.closest('.elementor-control-acf_field_names').length > 0;
            const isMergeMode = $this.closest('.elementor-control-acf_merge_mode').length > 0;

            // Debounce to avoid too many refreshes while typing
            clearTimeout(acfFieldNamesTimeout);
            acfFieldNamesTimeout = setTimeout(function () {
                // Find the currently edited element
                const $activeElement = $('.elementor-element.elementor-element-edit-mode');
                if ($activeElement.length) {
                    const elementId = $activeElement.data('id');
                    if (elementId && typeof elementor !== 'undefined') {
                        // Get the element model
                        const elementModel = elementor.getCurrentElement ? elementor.getCurrentElement() : null;
                        if (elementModel) {
                            // Explicitly update model setting to ensure it has latest value
                            // This fixes race condition where render happens before model update
                            if (isAcfFieldNames) {
                                elementModel.setSetting('acf_field_names', value);
                            } else if (isMergeMode) {
                                elementModel.setSetting('acf_merge_mode', value);
                            }

                            // The setSetting call above will trigger the 'change:settings' listener 
                            // defined in initElementorEditor, which handles the refresh.
                            // But we can also force render just in case.
                            if (elementModel.view) {
                                elementModel.view.render();
                            }
                        }
                    }
                }
            }, 500); // Wait 500ms after user stops typing
        });
    }

    // Initialize when DOM is ready
    $(document).ready(function () {
        anchorkitDebugLog('[AnchorKit] Document ready, initializing...');
        anchorkitDebugLog('[AnchorKit] Reset config available:', !!window.anchorkitElementorResetConfig);

        initAnchorKitResetButtons();

        // Wait for Elementor to be ready
        if (typeof elementor !== 'undefined' && elementor.on) {
            anchorkitDebugLog('[AnchorKit] Elementor already available');
            initElementorEditor();
            setupDirectControlListeners();
        } else {
            anchorkitDebugLog('[AnchorKit] Waiting for Elementor to initialize...');
            // Wait for Elementor to load
            $(window).on('elementor:init', function () {
                anchorkitDebugLog('[AnchorKit] Elementor initialized');
                initElementorEditor();
                setupDirectControlListeners();
            });
        }
    });

    // Also try to initialize when Elementor panel opens (backup approach)
    if (typeof elementor !== 'undefined') {
        elementor.on('panel:init', function () {
            anchorkitDebugLog('[AnchorKit] Panel init event');
            if (!resetHandlersBound) {
                initAnchorKitResetButtons();
            }
        });
    }

    // Direct button handler function
    function handleResetButtonClick(event) {
        event.preventDefault();
        event.stopPropagation();

        var button = event.currentTarget || event.target;
        var $button = $(button);

        anchorkitDebugLog('[AnchorKit] Direct click handler triggered');

        if ($button.prop('disabled') || $button.attr('aria-disabled') === 'true') {
            anchorkitDebugLog('[AnchorKit] Button is disabled');
            return;
        }

        var target = $button.data('resetTarget') || $button.attr('data-reset-target');
        var label = $button.data('resetLabel') || $button.attr('data-reset-label') || '';

        anchorkitDebugLog('[AnchorKit] Target:', target, 'Label:', label);

        var runtimeConfig = getResetConfig();
        if (!runtimeConfig) {
            console.warn('[AnchorKit] Reset configuration not loaded. Please refresh the editor.');
            return;
        }

        var sections = runtimeConfig.sections || {};
        var strings = runtimeConfig.strings || {};
        var controls = target === 'all'
            ? runtimeConfig.all_controls
            : (sections[target] ? sections[target].controls : null);

        if (!controls) {
            console.warn('[AnchorKit] No settings found for this section. Target:', target, 'Available:', Object.keys(sections));
            return;
        }

        var confirmMessage = target === 'all'
            ? (strings.allConfirm || 'Reset all settings to defaults?')
            : ((strings.sectionConfirm || 'Reset %s settings to defaults?').replace('%s', label));

        if (!window.confirm(confirmMessage)) {
            return;
        }

        var model = getActiveAnchorKitModel();
        if (!model) {
            console.warn('[AnchorKit] ' + (strings.noWidget || 'Could not find the widget. Make sure it is selected.'));
            return;
        }

        $button.prop('disabled', true).attr('aria-disabled', 'true');

        var success = applyResetValues(model, controls);

        if (success) {
            var successMessage = target === 'all'
                ? (strings.allSuccess || 'Widget reset to defaults.')
                : ((strings.sectionSuccess || '%s settings reset to defaults.').replace('%s', label));
            showResetMessage(successMessage, false);
        } else {
            showResetMessage('Failed to reset. Check console.', true);
        }

        setTimeout(function () {
            $button.prop('disabled', false).attr('aria-disabled', 'false');
        }, 400);
    }

    // Bind handlers directly to buttons when found
    function bindDirectHandlers() {
        var $buttons = $('.anchorkit-el-reset-button');
        if ($buttons.length) {
            anchorkitDebugLog('[AnchorKit] Found', $buttons.length, 'reset button(s), binding direct handlers');
            $buttons.each(function () {
                var button = this;
                // Remove any existing handler to avoid duplicates
                button.removeEventListener('click', handleResetButtonClick);
                // Add native click handler
                button.addEventListener('click', handleResetButtonClick, true);
            });
        }
    }

    // Use MutationObserver to detect when reset buttons are added to DOM
    function observeForResetButtons() {
        var observer = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                if (mutation.addedNodes && mutation.addedNodes.length) {
                    mutation.addedNodes.forEach(function (node) {
                        if (node.nodeType === 1) { // Element node
                            var $node = $(node);
                            var $buttons = $node.find('.anchorkit-el-reset-button');
                            if ($node.hasClass('anchorkit-el-reset-button')) {
                                $buttons = $buttons.add($node);
                            }
                            if ($buttons.length) {
                                anchorkitDebugLog('[AnchorKit] Reset button(s) detected in DOM via MutationObserver');
                                // Bind direct handlers to newly added buttons
                                bindDirectHandlers();
                                // Also ensure delegation is set up
                                if (!resetHandlersBound) {
                                    initAnchorKitResetButtons();
                                }
                            }
                        }
                    });
                }
            });
        });

        // Observe the entire document for changes
        observer.observe(document.body, {
            childList: true,
            subtree: true
        });

        anchorkitDebugLog('[AnchorKit] MutationObserver active');

        // Also try binding to any existing buttons
        bindDirectHandlers();
    }

    // Start observing after a short delay to let Elementor initialize
    setTimeout(observeForResetButtons, 1000);

    // Also try binding periodically for the first few seconds
    var bindAttempts = 0;
    var bindInterval = setInterval(function () {
        bindDirectHandlers();
        bindAttempts++;
        if (bindAttempts > 10) {
            clearInterval(bindInterval);
        }
    }, 500);

})(jQuery);
