/**
 * Entity Selector - Preview Module
 * Reusable preview popover component with filter and load more
 * @partial _preview.js
 */

(function($) {
    'use strict';

    window._EntitySelectorMixins = window._EntitySelectorMixins || {};

    window._EntitySelectorMixins.preview = {

        // =========================================================================
        // HEADER & TOGGLE UPDATES
        // =========================================================================

        updateHeaderTotalCount: function() {
            var self = this;
            var total = 0;

            this.$wrapper.find('.target-block-tab .tab-badge').each(function() {
                var $badge = $(this);
                if (!$badge.hasClass('loading')) {
                    var count = parseInt($badge.text(), 10);
                    if (!isNaN(count)) {
                        total += count;
                    }
                }
            });

            var $totalBadge = this.$wrapper.find('.trait-total-count');
            if (total > 0) {
                // Update count while preserving icon structure
                var $countValue = $totalBadge.find('.count-value');
                if ($countValue.length) {
                    $countValue.text(total);
                } else {
                    // Fallback: set HTML with icon
                    $totalBadge.html(self.esIcon('visibility') + ' <span class="count-value">' + total + '</span>');
                }
                $totalBadge.show();
            } else {
                $totalBadge.hide();
            }

            this.updateShowAllToggle();
        },

        updateShowAllToggle: function() {
            var $toggle = this.$wrapper.find('.trait-show-all-toggle');
            if (!$toggle.length) return;

            var $checkbox = $toggle.find('.show-all-checkbox');
            var hasData = this.$wrapper.find('.target-block-tab.has-data').length > 0;

            $checkbox.prop('checked', !hasData);
        },

        // =========================================================================
        // REUSABLE PREVIEW POPOVER COMPONENT
        // =========================================================================

        /**
         * Create and show a reusable preview popover
         * @param {Object} options Configuration options
         * @param {jQuery} options.$badge - The badge element to position against
         * @param {Array} options.items - Array of items to display
         * @param {number} options.totalCount - Total count of items
         * @param {boolean} options.hasMore - Whether more items are available
         * @param {string} options.entityLabel - Label for items (e.g., "products")
         * @param {string} options.previewType - Type identifier (e.g., "condition", "filter-group")
         * @param {Function} options.onLoadMore - Callback when load more is clicked
         * @param {Function} options.onFilter - Callback for AJAX filtering (receives query string)
         * @param {Object} options.context - Context data for load more
         */
        createPreviewPopover: function(options) {
            var self = this;
            var trans = this.config.trans || {};

            var $badge = options.$badge;
            var items = options.items || [];
            var totalCount = options.totalCount || 0;
            var hasMore = options.hasMore || false;
            var entityLabel = options.entityLabel || 'products';
            var previewType = options.previewType || 'default';

            // Build popover HTML
            var html = '<div class="target-preview-popover preview-type-' + previewType + '">';

            // Header with count and close button
            html += '<div class="preview-header">';
            html += '<span class="preview-count">' + totalCount + ' ' + entityLabel + '</span>';
            html += '<button type="button" class="preview-close">' + this.esIcon('close') + '</button>';
            html += '</div>';

            // Filter input
            html += '<div class="preview-filter">';
            html += '<input type="text" class="preview-filter-input" placeholder="' + (trans.filter_results || 'Filter results...') + '">';
            html += '</div>';

            // Items list
            if (items.length > 0) {
                html += '<div class="preview-list">';
                html += this.renderPreviewItems(items);
                html += '</div>';

                // Load more footer with select dropdown
                if (hasMore) {
                    var remaining = totalCount - items.length;
                    html += '<div class="preview-footer">';
                    html += '<div class="load-more-controls">';
                    html += '<span class="load-more-label">' + (trans.load || 'Load') + '</span>';
                    html += '<select class="load-more-select">';
                    if (remaining >= 10) html += '<option value="10">10</option>';
                    if (remaining >= 20) html += '<option value="20" selected>20</option>';
                    if (remaining >= 50) html += '<option value="50">50</option>';
                    if (remaining >= 100) html += '<option value="100">100</option>';
                    html += '<option value="' + remaining + '">' + (trans.all || 'All') + ' (' + remaining + ')</option>';
                    html += '</select>';
                    html += '<span class="load-more-of">' + (trans.of || 'of') + ' <span class="remaining-count">' + remaining + '</span> ' + (trans.remaining || 'remaining') + '</span>';
                    html += '<button type="button" class="btn-load-more">' + self.esIcon('add') + '</button>';
                    html += '</div>';
                    html += '</div>';
                }
            } else {
                html += '<div class="preview-empty">' + (trans.no_preview || 'No items to preview') + '</div>';
            }

            html += '</div>';

            // Create and append popover
            var $popover = $(html);
            $('body').append($popover);

            // Store references
            this.$previewPopover = $popover;
            this.$previewList = $popover.find('.preview-list');
            this.previewLoadedCount = items.length;
            this.previewTotalCount = totalCount;
            this.previewContext = options.context || {};
            this.previewOnLoadMore = options.onLoadMore || null;
            this.previewOnFilter = options.onFilter || null;
            this.previewCurrentFilter = '';
            this.previewEntityLabel = entityLabel;

            // Event handlers
            $popover.find('.preview-close').on('click', function() {
                self.hidePreviewPopover();
            });

            // Filter input with AJAX support
            var $filterInput = $popover.find('.preview-filter-input');
            if (options.onFilter) {
                // Use AJAX filtering with debounce
                var debouncedFilter = this.debounce(function(query) {
                    self.previewCurrentFilter = query;
                    self.showFilterLoading(true);
                    options.onFilter.call(self, query);
                }, 300);

                $filterInput.on('input', function() {
                    var query = $(this).val().trim();
                    if (query === self.previewCurrentFilter) return;
                    debouncedFilter(query);
                });
            } else {
                // Fallback to client-side filtering
                $filterInput.on('input', function() {
                    var query = $(this).val().toLowerCase().trim();
                    self.filterPreviewItems(query);
                });
            }

            if (options.onLoadMore) {
                $popover.find('.btn-load-more').on('click', function() {
                    var $btn = $(this);
                    var $controls = $btn.closest('.load-more-controls');
                    var $select = $controls.find('.load-more-select');

                    if ($btn.hasClass('loading')) return;

                    $btn.addClass('loading');
                    $btn.find('i').replaceWith(self.esIcon('progress_activity', 'es-spin'));
                    $select.prop('disabled', true);

                    // Get selected load count
                    var loadCount = parseInt($select.val(), 10) || 20;
                    self.previewLoadCount = loadCount;

                    options.onLoadMore.call(self, $btn);
                });
            }

            // Position popover below badge
            var badgeOffset = $badge.offset();
            var badgeHeight = $badge.outerHeight();
            var badgeWidth = $badge.outerWidth();
            var popoverWidth = $popover.outerWidth();

            var leftPos = badgeOffset.left + (badgeWidth / 2) - (popoverWidth / 2);
            var minLeft = 10;
            var maxLeft = $(window).width() - popoverWidth - 10;
            leftPos = Math.max(minLeft, Math.min(leftPos, maxLeft));

            $popover.css({
                position: 'absolute',
                top: badgeOffset.top + badgeHeight + 8,
                left: leftPos,
                zIndex: 10000
            });

            // Show with transition
            $popover.addClass('show');

            return $popover;
        },

        /**
         * Update popover after loading more items
         */
        updatePreviewPopover: function(items, hasMore) {
            var trans = this.config.trans || {};

            // Update list
            this.$previewList.html(this.renderPreviewItems(items));
            this.previewLoadedCount = items.length;

            // Update or remove load more controls
            var $footer = this.$previewPopover.find('.preview-footer');
            if (hasMore) {
                var remaining = this.previewTotalCount - items.length;
                var $controls = $footer.find('.load-more-controls');
                var $btn = $controls.find('.btn-load-more');
                var $select = $controls.find('.load-more-select');

                // Reset button state
                $btn.removeClass('loading');
                $btn.find('i').replaceWith(this.esIcon('add'));
                $select.prop('disabled', false);

                // Update remaining count
                $controls.find('.remaining-count').text(remaining);

                // Update select options
                $select.empty();
                if (remaining >= 10) $select.append('<option value="10">10</option>');
                if (remaining >= 20) $select.append('<option value="20" selected>20</option>');
                if (remaining >= 50) $select.append('<option value="50">50</option>');
                if (remaining >= 100) $select.append('<option value="100">100</option>');
                $select.append('<option value="' + remaining + '">' + (trans.all || 'All') + ' (' + remaining + ')</option>');
            } else {
                $footer.remove();
            }

            // Re-apply filter if active
            var filterQuery = this.$previewPopover.find('.preview-filter-input').val();
            if (filterQuery) {
                this.filterPreviewItems(filterQuery.toLowerCase().trim());
            }
        },

        /**
         * Render preview items HTML with consistent format
         */
        renderPreviewItems: function(items) {
            var self = this;
            var html = '';

            for (var i = 0; i < items.length; i++) {
                var item = items[i];
                var itemClass = 'preview-item';
                if (item.isCombination) itemClass += ' is-combination';

                // Build data attributes for filtering
                var dataAttrs = '';
                dataAttrs += ' data-name="' + this.escapeAttr((item.name || '').toLowerCase()) + '"';
                dataAttrs += ' data-ref="' + this.escapeAttr((item.reference || '').toLowerCase()) + '"';
                if (item.attributes) {
                    dataAttrs += ' data-attrs="' + this.escapeAttr((item.attributes || '').toLowerCase()) + '"';
                }

                html += '<div class="' + itemClass + '"' + dataAttrs + '>';

                // Image or placeholder
                if (item.image) {
                    html += '<img src="' + this.escapeAttr(item.image) + '" class="preview-item-image" alt="">';
                } else {
                    html += '<div class="preview-item-icon">' + self.esIcon('inventory_2') + '</div>';
                }

                // Info section
                html += '<div class="preview-item-info">';
                html += '<div class="preview-item-name">' + this.escapeHtml(item.name || 'Unnamed') + '</div>';

                // Meta line (reference, manufacturer, category, attributes)
                var meta = [];
                if (item.reference) {
                    meta.push('Ref: ' + item.reference);
                }
                if (item.manufacturer) {
                    meta.push(item.manufacturer);
                }
                if (item.category) {
                    meta.push(item.category);
                }
                if (item.attributes) {
                    meta.push(item.attributes);
                }

                if (meta.length > 0) {
                    html += '<div class="preview-item-meta">' + this.escapeHtml(meta.join(' • ')) + '</div>';
                }

                html += '</div>'; // .preview-item-info

                // Price column (always show if available)
                if (typeof item.price !== 'undefined' && item.price !== null) {
                    html += '<div class="preview-item-price">' + this.formatPrice(item.price) + '</div>';
                } else if (item.price_formatted) {
                    html += '<div class="preview-item-price">' + this.escapeHtml(item.price_formatted) + '</div>';
                }

                // Status badge if inactive
                if (typeof item.active !== 'undefined' && !item.active) {
                    html += '<span class="preview-item-badge badge-inactive">Inactive</span>';
                }

                html += '</div>'; // .preview-item
            }

            return html;
        },

        /**
         * Filter preview items by query (client-side fallback)
         */
        filterPreviewItems: function(query) {
            if (!this.$previewList) return;

            var $items = this.$previewList.find('.preview-item');

            if (!query) {
                $items.show();
                return;
            }

            $items.each(function() {
                var $item = $(this);
                var name = $item.data('name') || '';
                var ref = $item.data('ref') || '';
                var attrs = $item.data('attrs') || '';

                var matches = name.indexOf(query) !== -1 ||
                              ref.indexOf(query) !== -1 ||
                              attrs.indexOf(query) !== -1;

                $item.toggle(matches);
            });
        },

        /**
         * Show/hide loading indicator during AJAX filter
         */
        showFilterLoading: function(show) {
            if (!this.$previewPopover) return;

            var $list = this.$previewList;
            if (!$list) return;

            if (show) {
                // Lock the popover width before filtering to prevent resize
                if (!this.previewLockedWidth) {
                    this.previewLockedWidth = this.$previewPopover.outerWidth();
                    this.$previewPopover.css('width', this.previewLockedWidth + 'px');
                }

                $list.addClass('filtering');
                // Add overlay if not exists
                if (!$list.find('.filter-loading-overlay').length) {
                    $list.append('<div class="filter-loading-overlay">' + self.esIcon('progress_activity', 'es-spin') + '</div>');
                }
            } else {
                $list.removeClass('filtering');
                $list.find('.filter-loading-overlay').remove();
            }
        },

        /**
         * Update preview popover with filtered AJAX results
         * @param {Object} response - AJAX response with items, count, hasMore
         */
        updatePreviewPopoverFiltered: function(response) {
            var trans = this.config.trans || {};

            this.showFilterLoading(false);

            if (!response.success) {
                return;
            }

            var items = response.items || [];
            var filteredCount = response.count || 0;
            var hasMore = response.hasMore || false;

            // Update header count to show filtered count
            var $header = this.$previewPopover.find('.preview-header');
            var entityLabel = this.previewEntityLabel || 'items';
            $header.find('.preview-count').text(filteredCount + ' ' + entityLabel);

            // Update list
            if (items.length > 0) {
                this.$previewList.html(this.renderPreviewItems(items));
                this.previewLoadedCount = items.length;
                this.previewTotalCount = filteredCount;
            } else {
                var noResultsText = trans.no_filter_results || 'No matching items found';
                this.$previewList.html('<div class="preview-empty">' + noResultsText + '</div>');
                this.previewLoadedCount = 0;
                this.previewTotalCount = 0;
            }

            // Update or create footer for load more
            var $footer = this.$previewPopover.find('.preview-footer');
            if (hasMore && items.length > 0) {
                var remaining = filteredCount - items.length;
                if ($footer.length) {
                    var $controls = $footer.find('.load-more-controls');
                    var $btn = $controls.find('.btn-load-more');
                    var $select = $controls.find('.load-more-select');

                    $btn.removeClass('loading');
                    $btn.find('i').replaceWith(self.esIcon('add'));
                    $select.prop('disabled', false);
                    $controls.find('.remaining-count').text(remaining);

                    $select.empty();
                    if (remaining >= 10) $select.append('<option value="10">10</option>');
                    if (remaining >= 20) $select.append('<option value="20" selected>20</option>');
                    if (remaining >= 50) $select.append('<option value="50">50</option>');
                    if (remaining >= 100) $select.append('<option value="100">100</option>');
                    $select.append('<option value="' + remaining + '">' + (trans.all || 'All') + ' (' + remaining + ')</option>');
                } else {
                    // Create footer
                    var footerHtml = '<div class="preview-footer">';
                    footerHtml += '<div class="load-more-controls">';
                    footerHtml += '<span class="load-more-label">' + (trans.load || 'Load') + '</span>';
                    footerHtml += '<select class="load-more-select">';
                    if (remaining >= 10) footerHtml += '<option value="10">10</option>';
                    if (remaining >= 20) footerHtml += '<option value="20" selected>20</option>';
                    if (remaining >= 50) footerHtml += '<option value="50">50</option>';
                    if (remaining >= 100) footerHtml += '<option value="100">100</option>';
                    footerHtml += '<option value="' + remaining + '">' + (trans.all || 'All') + ' (' + remaining + ')</option>';
                    footerHtml += '</select>';
                    footerHtml += '<span class="load-more-of">' + (trans.of || 'of') + ' <span class="remaining-count">' + remaining + '</span> ' + (trans.remaining || 'remaining') + '</span>';
                    footerHtml += '<button type="button" class="btn-load-more">' + self.esIcon('add') + '</button>';
                    footerHtml += '</div>';
                    footerHtml += '</div>';

                    var $newFooter = $(footerHtml);
                    this.$previewList.after($newFooter);

                    // Rebind load more click
                    var self = this;
                    if (this.previewOnLoadMore) {
                        $newFooter.find('.btn-load-more').on('click', function() {
                            var $btn = $(this);
                            var $controls = $btn.closest('.load-more-controls');
                            var $select = $controls.find('.load-more-select');

                            if ($btn.hasClass('loading')) return;

                            $btn.addClass('loading');
                            $btn.find('i').replaceWith(self.esIcon('progress_activity', 'es-spin'));
                            $select.prop('disabled', true);

                            var loadCount = parseInt($select.val(), 10) || 20;
                            self.previewLoadCount = loadCount;

                            self.previewOnLoadMore.call(self, $btn);
                        });
                    }
                }
            } else {
                $footer.remove();
            }
        },

        /**
         * Format price for display
         */
        formatPrice: function(price) {
            if (typeof price !== 'number') {
                price = parseFloat(price) || 0;
            }
            // Use currency format from config if available
            var currencySign = (this.config && this.config.currency_sign) || '€';
            var currencyFormat = (this.config && this.config.currency_format) || 'right';

            var formatted = price.toFixed(2);

            if (currencyFormat === 'left') {
                return currencySign + ' ' + formatted;
            } else {
                return formatted + ' ' + currencySign;
            }
        },

        /**
         * Hide and clean up preview popover
         */
        hidePreviewPopover: function() {
            if (this.$activeBadge) {
                this.$activeBadge.removeClass('popover-open loading');
                this.$activeBadge = null;
            }
            if (this.$previewPopover) {
                this.$previewPopover.remove();
                this.$previewPopover = null;
            }
            this.$previewList = null;
            this.previewContext = null;
            this.previewOnLoadMore = null;
            this.previewOnFilter = null;
            this.previewCurrentFilter = '';
            this.previewEntityLabel = null;
            this.previewLockedWidth = null;
        },

        // =========================================================================
        // TAB PREVIEW (Block tab badge click)
        // =========================================================================

        showPreviewPopover: function($tab) {
            var self = this;
            var previewData = $tab.data('previewData');

            if (!previewData) {
                return;
            }

            this.hidePreviewPopover();

            var $badge = $tab.find('.tab-badge');
            $badge.addClass('popover-open');
            this.$activeBadge = $badge;

            var items = previewData.items || previewData.products || [];
            var blockType = $tab.data('blockType');
            var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};
            var entityLabelPlural = blockConfig.entity_label_plural || 'items';

            this.previewBlockType = blockType;

            // If items not loaded yet, fetch them first
            if (items.length === 0 && previewData.count > 0) {
                $badge.addClass('loading');
                this.fetchTabPreviewItems($tab, function(fetchedItems, hasMore) {
                    $badge.removeClass('loading');
                    self.createPreviewPopover({
                        $badge: $badge,
                        items: fetchedItems,
                        totalCount: previewData.count,
                        hasMore: hasMore,
                        entityLabel: entityLabelPlural,
                        previewType: 'tab',
                        context: { $tab: $tab, blockType: blockType },
                        onLoadMore: function($btn) {
                            self.loadMoreTabPreviewItems($tab, $btn);
                        },
                        onFilter: function(query) {
                            self.filterTabPreviewItems($tab, query);
                        }
                    });
                });
                return;
            }

            this.createPreviewPopover({
                $badge: $badge,
                items: items,
                totalCount: previewData.count,
                hasMore: previewData.hasMore,
                entityLabel: entityLabelPlural,
                previewType: 'tab',
                context: { $tab: $tab, blockType: blockType },
                onLoadMore: function($btn) {
                    self.loadMoreTabPreviewItems($tab, $btn);
                },
                onFilter: function(query) {
                    self.filterTabPreviewItems($tab, query);
                }
            });
        },

        /**
         * Fetch preview items for a tab via AJAX
         */
        fetchTabPreviewItems: function($tab, callback) {
            var self = this;
            var blockType = $tab.data('blockType');

            var $hiddenInput = this.$wrapper.find('input[name="' + this.config.name + '"]');
            var savedData = {};
            try {
                savedData = JSON.parse($hiddenInput.val() || '{}');
            } catch (e) {
                callback([], false);
                return;
            }

            var groups = (savedData[blockType] && savedData[blockType].groups) ? savedData[blockType].groups : [];
            if (groups.length === 0) {
                callback([], false);
                return;
            }

            var data = {};
            data[blockType] = { groups: groups };

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewEntitySelector',
                    trait: 'EntitySelector',
                    conditions: JSON.stringify(data),
                    block_type: blockType,
                    limit: 20,
                    offset: 0
                },
                success: function(response) {
                    var items = response.items || response.products || [];
                    var hasMore = response.hasMore || (response.count > items.length);
                    // Update stored preview data with items
                    $tab.data('previewData', response);
                    callback(items, hasMore);
                },
                error: function() {
                    callback([], false);
                }
            });
        },

        /**
         * AJAX filter handler for tab preview
         */
        filterTabPreviewItems: function($tab, query) {
            var self = this;
            var blockType = this.previewBlockType;

            var $hiddenInput = this.$wrapper.find('input[name="' + this.config.name + '"]');
            var savedData = {};
            try {
                savedData = JSON.parse($hiddenInput.val() || '{}');
            } catch (e) {
                self.showFilterLoading(false);
                return;
            }

            var groups = (savedData[blockType] && savedData[blockType].groups) ? savedData[blockType].groups : [];
            if (groups.length === 0) {
                self.showFilterLoading(false);
                return;
            }

            var data = {};
            data[blockType] = { groups: groups };

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewTargetConditions',
                    trait: 'TargetConditions',
                    conditions: JSON.stringify(data),
                    block_type: blockType,
                    filter: query,
                    limit: 20,
                    offset: 0
                },
                success: function(response) {
                    self.updatePreviewPopoverFiltered(response);
                },
                error: function() {
                    self.showFilterLoading(false);
                }
            });
        },

        loadMoreTabPreviewItems: function($tab, $btn) {
            var self = this;
            var blockType = this.previewBlockType;

            var $hiddenInput = this.$wrapper.find('input[name="' + this.config.name + '"]');
            var savedData = {};
            try {
                savedData = JSON.parse($hiddenInput.val() || '{}');
            } catch (e) {
                return;
            }

            var groups = (savedData[blockType] && savedData[blockType].groups) ? savedData[blockType].groups : [];
            if (groups.length === 0) return;

            var data = {};
            data[blockType] = { groups: groups };

            var loadCount = this.previewLoadCount || 20;

            // Include current filter in load more request
            var ajaxData = {
                ajax: 1,
                action: 'previewTargetConditions',
                trait: 'TargetConditions',
                conditions: JSON.stringify(data),
                block_type: blockType,
                limit: self.previewLoadedCount + loadCount,
                offset: 0
            };
            if (self.previewCurrentFilter) {
                ajaxData.filter = self.previewCurrentFilter;
            }

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: ajaxData,
                success: function(response) {
                    var items = response.items || response.products || [];
                    if (response.success && items.length > 0) {
                        $tab.data('previewData', response);
                        self.previewTotalCount = response.count;
                        self.updatePreviewPopover(items, response.hasMore);
                    }
                },
                error: function() {
                    var $controls = $btn.closest('.load-more-controls');
                    var $select = $controls.find('.load-more-select');
                    $btn.removeClass('loading');
                    $btn.find('i').replaceWith(self.esIcon('add'));
                    $select.prop('disabled', false);
                }
            });
        },

        // =========================================================================
        // CONDITION PREVIEW (Single condition badge click)
        // =========================================================================

        showConditionPreviewPopover: function($badge) {
            var self = this;
            var conditionData = $badge.data('conditionData');

            if (!conditionData) {
                return;
            }

            // Check if this is a country holidays badge
            if (conditionData.isCountryHolidays && conditionData.countryIds) {
                this.showCountriesHolidayPreview($badge, conditionData.countryIds);
                return;
            }

            this.hidePreviewPopover();

            $badge.addClass('popover-open loading');
            this.$activeBadge = $badge;

            var blockType = conditionData.blockType || 'products';
            var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};
            var entityLabelPlural = blockConfig.entity_label_plural || 'products';

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewConditionItems',
                    trait: 'EntitySelector',
                    method: conditionData.method,
                    values: JSON.stringify(conditionData.values),
                    block_type: blockType,
                    limit: 10
                },
                success: function(response) {
                    $badge.removeClass('loading');

                    if (response.success) {
                        self.createPreviewPopover({
                            $badge: $badge,
                            items: response.items || [],
                            totalCount: response.count,
                            hasMore: response.hasMore,
                            entityLabel: entityLabelPlural,
                            previewType: 'condition',
                            context: { conditionData: conditionData, blockType: blockType },
                            onLoadMore: function($btn) {
                                self.loadMoreConditionItems($btn);
                            },
                            onFilter: function(query) {
                                self.filterConditionItems(query);
                            }
                        });
                    } else {
                        $badge.removeClass('popover-open');
                        self.$activeBadge = null;
                    }
                },
                error: function() {
                    $badge.removeClass('loading popover-open');
                    self.$activeBadge = null;
                }
            });
        },

        /**
         * AJAX filter handler for condition preview
         */
        filterConditionItems: function(query) {
            var self = this;
            var ctx = this.previewContext;

            if (!ctx || !ctx.conditionData) {
                self.showFilterLoading(false);
                return;
            }

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewConditionItems',
                    trait: 'EntitySelector',
                    method: ctx.conditionData.method,
                    values: JSON.stringify(ctx.conditionData.values),
                    block_type: ctx.blockType,
                    filter: query,
                    limit: 20
                },
                success: function(response) {
                    self.updatePreviewPopoverFiltered(response);
                },
                error: function() {
                    self.showFilterLoading(false);
                }
            });
        },

        loadMoreConditionItems: function($btn) {
            var self = this;
            var ctx = this.previewContext;

            if (!ctx || !ctx.conditionData) return;

            var loadCount = this.previewLoadCount || 20;

            // Include current filter in load more request
            var ajaxData = {
                ajax: 1,
                action: 'previewConditionItems',
                trait: 'EntitySelector',
                method: ctx.conditionData.method,
                values: JSON.stringify(ctx.conditionData.values),
                block_type: ctx.blockType,
                limit: self.previewLoadedCount + loadCount
            };
            if (self.previewCurrentFilter) {
                ajaxData.filter = self.previewCurrentFilter;
            }

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: ajaxData,
                success: function(response) {
                    if (response.success) {
                        self.previewTotalCount = response.count;
                        self.updatePreviewPopover(response.items || [], response.hasMore);
                    }
                },
                error: function() {
                    var $controls = $btn.closest('.load-more-controls');
                    var $select = $controls.find('.load-more-select');
                    $btn.removeClass('loading');
                    $btn.find('i').replaceWith(self.esIcon('add'));
                    $select.prop('disabled', false);
                }
            });
        },

        // =========================================================================
        // GROUP PREVIEW (Selection group badge click)
        // =========================================================================

        showGroupPreviewPopover: function($badge, $group, blockType) {
            var self = this;

            if (!$group) {
                $group = $badge.closest('.selection-group');
            }

            if (!blockType) {
                var $block = $badge.closest('.target-block');
                blockType = $block.data('blockType') || 'products';
            }

            var groupData = $badge.data('groupData');

            if (!groupData) {
                groupData = this.serializeGroup($group, blockType);
            }

            if (!groupData || !groupData.include) {
                return;
            }

            this.hidePreviewPopover();

            $badge.addClass('popover-open loading');
            this.$activeBadge = $badge;

            var blockConfig = this.config.blocks && this.config.blocks[blockType] ? this.config.blocks[blockType] : {};
            var entityLabelPlural = blockConfig.entity_label_plural || 'products';

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewGroupItems',
                    trait: 'EntitySelector',
                    group_data: JSON.stringify(groupData),
                    block_type: blockType,
                    limit: 10
                },
                success: function(response) {
                    $badge.removeClass('loading');

                    if (response.success) {
                        self.createPreviewPopover({
                            $badge: $badge,
                            items: response.items || [],
                            totalCount: response.count,
                            hasMore: response.hasMore,
                            entityLabel: entityLabelPlural,
                            previewType: 'group',
                            context: { groupData: groupData, blockType: blockType, $group: $group },
                            onLoadMore: function($btn) {
                                self.loadMoreGroupItems($btn);
                            },
                            onFilter: function(query) {
                                self.filterGroupItems(query);
                            }
                        });
                    } else {
                        $badge.removeClass('popover-open');
                        self.$activeBadge = null;
                    }
                },
                error: function() {
                    $badge.removeClass('loading popover-open');
                    self.$activeBadge = null;
                }
            });
        },

        /**
         * AJAX filter handler for group preview
         */
        filterGroupItems: function(query) {
            var self = this;
            var ctx = this.previewContext;

            if (!ctx || !ctx.groupData) {
                self.showFilterLoading(false);
                return;
            }

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewGroupItems',
                    trait: 'EntitySelector',
                    group_data: JSON.stringify(ctx.groupData),
                    block_type: ctx.blockType,
                    filter: query,
                    limit: 20
                },
                success: function(response) {
                    self.updatePreviewPopoverFiltered(response);
                },
                error: function() {
                    self.showFilterLoading(false);
                }
            });
        },

        loadMoreGroupItems: function($btn) {
            var self = this;
            var ctx = this.previewContext;

            if (!ctx || !ctx.groupData) return;

            var loadCount = this.previewLoadCount || 20;

            // Include current filter in load more request
            var ajaxData = {
                ajax: 1,
                action: 'previewGroupItems',
                trait: 'EntitySelector',
                group_data: JSON.stringify(ctx.groupData),
                block_type: ctx.blockType,
                limit: self.previewLoadedCount + loadCount
            };
            if (self.previewCurrentFilter) {
                ajaxData.filter = self.previewCurrentFilter;
            }

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: ajaxData,
                success: function(response) {
                    if (response.success) {
                        self.previewTotalCount = response.count;
                        self.updatePreviewPopover(response.items || [], response.hasMore);
                    }
                },
                error: function() {
                    $btn.removeClass('loading');
                    $btn.find('.load-more-text').show();
                    $btn.find('.load-more-loading').hide();
                }
            });
        },

        // =========================================================================
        // FILTER GROUP PREVIEW (Attribute/Feature group toggle badge)
        // =========================================================================

        showFilterGroupPreviewPopover: function($badge, groupId, groupType, groupName) {
            var self = this;

            this.hidePreviewPopover();

            $badge.addClass('popover-open loading');
            this.$activeBadge = $badge;

            var entityLabelPlural = 'products';

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewFilterGroupProducts',
                    trait: 'EntitySelector',
                    group_id: groupId,
                    group_type: groupType,
                    limit: 10
                },
                success: function(response) {
                    $badge.removeClass('loading');

                    if (response.success) {
                        self.createPreviewPopover({
                            $badge: $badge,
                            items: response.items || [],
                            totalCount: response.count || 0,
                            hasMore: response.hasMore || false,
                            entityLabel: entityLabelPlural,
                            previewType: 'filter-group',
                            context: { groupId: groupId, groupType: groupType, groupName: groupName },
                            onLoadMore: function($btn) {
                                self.loadMoreFilterGroupItems($btn);
                            },
                            onFilter: function(query) {
                                self.filterFilterGroupItems(query);
                            }
                        });
                    } else {
                        $badge.removeClass('popover-open');
                        self.$activeBadge = null;
                    }
                },
                error: function() {
                    $badge.removeClass('loading popover-open');
                    self.$activeBadge = null;
                }
            });
        },

        /**
         * AJAX filter handler for filter group preview
         */
        filterFilterGroupItems: function(query) {
            var self = this;
            var ctx = this.previewContext;

            if (!ctx || !ctx.groupId) {
                self.showFilterLoading(false);
                return;
            }

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewFilterGroupProducts',
                    trait: 'EntitySelector',
                    group_id: ctx.groupId,
                    group_type: ctx.groupType,
                    filter: query,
                    limit: 20
                },
                success: function(response) {
                    self.updatePreviewPopoverFiltered(response);
                },
                error: function() {
                    self.showFilterLoading(false);
                }
            });
        },

        loadMoreFilterGroupItems: function($btn) {
            var self = this;
            var ctx = this.previewContext;

            if (!ctx || !ctx.groupId) return;

            var loadCount = this.previewLoadCount || 20;

            // Include current filter in load more request
            var ajaxData = {
                ajax: 1,
                action: 'previewFilterGroupProducts',
                trait: 'EntitySelector',
                group_id: ctx.groupId,
                group_type: ctx.groupType,
                limit: self.previewLoadedCount + loadCount
            };
            if (self.previewCurrentFilter) {
                ajaxData.filter = self.previewCurrentFilter;
            }

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: ajaxData,
                success: function(response) {
                    if (response.success) {
                        self.previewTotalCount = response.count;
                        self.updatePreviewPopover(response.items || [], response.hasMore);
                    }
                },
                error: function() {
                    $btn.removeClass('loading');
                    $btn.find('.load-more-text').show();
                    $btn.find('.load-more-loading').hide();
                }
            });
        },

        // =========================================================================
        // CATEGORY ITEMS PREVIEW (products/pages in a category)
        // =========================================================================

        showCategoryItemsPreview: function($badge, categoryId, categoryName, entityType) {
            var self = this;

            this.hidePreviewPopover();

            $badge.addClass('popover-open loading');
            this.$activeBadge = $badge;

            var isProducts = (entityType === 'categories');
            var entityLabelPlural = isProducts ? 'products' : 'pages';
            var action = isProducts ? 'previewCategoryProducts' : 'previewCategoryPages';

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: action,
                    trait: 'EntitySelector',
                    category_id: categoryId,
                    limit: 10
                },
                success: function(response) {
                    $badge.removeClass('loading');

                    if (response.success) {
                        self.createPreviewPopover({
                            $badge: $badge,
                            items: response.items || [],
                            totalCount: response.count || 0,
                            hasMore: response.hasMore || false,
                            entityLabel: entityLabelPlural,
                            previewType: 'category-items',
                            context: { categoryId: categoryId, categoryName: categoryName, entityType: entityType },
                            onLoadMore: function($btn) {
                                self.loadMoreCategoryItems($btn);
                            },
                            onFilter: function(query) {
                                self.filterCategoryItems(query);
                            }
                        });
                    } else {
                        $badge.removeClass('popover-open');
                        self.$activeBadge = null;
                    }
                },
                error: function() {
                    $badge.removeClass('loading popover-open');
                    self.$activeBadge = null;
                }
            });
        },

        loadMoreCategoryItems: function($btn) {
            var self = this;
            var ctx = this.previewContext;

            if (!ctx || !ctx.categoryId) return;

            var isProducts = (ctx.entityType === 'categories');
            var action = isProducts ? 'previewCategoryProducts' : 'previewCategoryPages';

            $btn.prop('disabled', true).find('i').addClass('es-spin');

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: action,
                    trait: 'EntitySelector',
                    category_id: ctx.categoryId,
                    offset: this.previewOffset,
                    limit: 10,
                    query: this.previewFilterQuery || ''
                },
                success: function(response) {
                    $btn.prop('disabled', false).find('i').removeClass('es-spin');

                    if (response.success && response.items) {
                        self.appendPreviewItems(response.items);
                        self.previewOffset += response.items.length;

                        if (!response.hasMore) {
                            $btn.hide();
                        }
                    }
                },
                error: function() {
                    $btn.prop('disabled', false).find('i').removeClass('es-spin');
                }
            });
        },

        filterCategoryItems: function(query) {
            var self = this;
            var ctx = this.previewContext;

            if (!ctx || !ctx.categoryId) {
                self.showFilterLoading(false);
                return;
            }

            var isProducts = (ctx.entityType === 'categories');
            var action = isProducts ? 'previewCategoryProducts' : 'previewCategoryPages';

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: action,
                    trait: 'EntitySelector',
                    category_id: ctx.categoryId,
                    query: query,
                    limit: 10
                },
                success: function(response) {
                    self.showFilterLoading(false);

                    if (response.success) {
                        self.replacePreviewItems(response.items || [], response.count || 0, response.hasMore || false);
                        self.previewOffset = response.items ? response.items.length : 0;
                        self.previewFilterQuery = query;
                    }
                },
                error: function() {
                    self.showFilterLoading(false);
                }
            });
        },

        // =========================================================================
        // PATTERN PREVIEW MODAL (for regex/pattern matching)
        // =========================================================================

        showPatternPreviewModal: function(pattern, entityType, caseSensitive, count) {
            var self = this;
            var trans = this.config.trans || {};

            var blockConfig = this.config.blocks && this.config.blocks[entityType] ? this.config.blocks[entityType] : {};
            var entityLabelPlural = blockConfig.entity_label_plural || 'items';
            var entityLabelSingular = blockConfig.entity_label || 'item';

            var html = '<div class="pattern-preview-modal-overlay">';
            html += '<div class="pattern-preview-modal">';
            html += '<div class="pattern-preview-header">';
            html += '<span class="pattern-preview-title">';
            html += this.esIcon('visibility') + ' ' + (trans.preview || 'Preview') + ': <code>' + this.escapeHtml(pattern) + '</code>';
            html += '</span>';
            html += '<span class="pattern-preview-count">' + count + ' ' + (count === 1 ? entityLabelSingular : entityLabelPlural) + '</span>';
            html += '<button type="button" class="pattern-preview-close">' + this.esIcon('close') + '</button>';
            html += '</div>';
            html += '<div class="pattern-preview-content">';
            html += '<div class="pattern-preview-loading">' + this.esIcon('progress_activity', 'es-spin') + ' ' + (trans.loading || 'Loading...') + '</div>';
            html += '</div>';
            html += '</div>';
            html += '</div>';

            var $modal = $(html);
            $('body').append($modal);

            $modal.find('.pattern-preview-close').on('click', function() {
                $modal.remove();
            });
            $modal.on('click', function(e) {
                if ($(e.target).hasClass('pattern-preview-modal-overlay')) {
                    $modal.remove();
                }
            });

            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'previewPatternMatches',
                    trait: 'TargetConditions',
                    pattern: pattern,
                    entity_type: entityType,
                    case_sensitive: caseSensitive ? 1 : 0,
                    limit: 50
                },
                success: function(response) {
                    if (response.success && response.items) {
                        var items = response.items;
                        var listHtml = '<div class="pattern-preview-list">';

                        if (items.length === 0) {
                            listHtml += '<div class="pattern-preview-empty">' + (trans.no_matches || 'No matches found') + '</div>';
                        } else {
                            for (var i = 0; i < items.length; i++) {
                                var item = items[i];
                                listHtml += '<div class="pattern-preview-item">';
                                if (item.image) {
                                    listHtml += '<img src="' + self.escapeAttr(item.image) + '" alt="" class="preview-item-image">';
                                }
                                listHtml += '<span class="preview-item-name">' + self.escapeHtml(item.name) + '</span>';
                                if (item.id) {
                                    listHtml += '<span class="preview-item-id">#' + item.id + '</span>';
                                }
                                listHtml += '</div>';
                            }

                            if (count > items.length) {
                                listHtml += '<div class="pattern-preview-more">... ' + (trans.and || 'and') + ' ' + (count - items.length) + ' ' + (trans.more || 'more') + '</div>';
                            }
                        }

                        listHtml += '</div>';
                        $modal.find('.pattern-preview-content').html(listHtml);
                    } else {
                        $modal.find('.pattern-preview-content').html('<div class="pattern-preview-error">' + (trans.error_loading || 'Error loading preview') + '</div>');
                    }
                },
                error: function() {
                    $modal.find('.pattern-preview-content').html('<div class="pattern-preview-error">' + (trans.error_loading || 'Error loading preview') + '</div>');
                }
            });
        },

        // =========================================================================
        // HELPER METHODS
        // =========================================================================

        refreshGroupPreviewIfOpen: function($group) {
            // Check if preview is for this group and refresh if needed
            if (!this.$activeBadge || !this.$previewPopover) {
                return;
            }
        },

        /**
         * Escape HTML special characters
         */
        escapeHtml: function(str) {
            if (!str) return '';
            return String(str)
                .replace(/&/g, '&amp;')
                .replace(/</g, '&lt;')
                .replace(/>/g, '&gt;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#39;');
        },

        /**
         * Escape attribute value
         */
        escapeAttr: function(str) {
            if (!str) return '';
            return String(str)
                .replace(/&/g, '&amp;')
                .replace(/"/g, '&quot;')
                .replace(/'/g, '&#39;');
        },

        // =========================================================================
        // TOTAL COUNT PREVIEW (Header total badge click)
        // =========================================================================

        /**
         * Show preview popover for total count badge
         * Displays a summary of all entity types with their counts
         */
        showTotalPreviewPopover: function($badge) {
            var self = this;
            var trans = this.config.trans || {};

            this.hidePreviewPopover();

            $badge.addClass('popover-open');
            this.$activeBadge = $badge;

            // Collect all entity types with data
            var summaryItems = [];
            this.$wrapper.find('.target-block-tab.has-data').each(function() {
                var $tab = $(this);
                var blockType = $tab.data('blockType');
                var $tabBadge = $tab.find('.tab-badge');
                var countText = $tabBadge.text().replace(/[^0-9]/g, '');
                var count = parseInt(countText, 10) || 0;

                if (count > 0) {
                    var blockConfig = self.config.blocks && self.config.blocks[blockType] ? self.config.blocks[blockType] : {};
                    var icon = $tab.find('.tab-label').prev('i').text() || 'widgets';
                    var label = $tab.find('.tab-label').text() || blockType;

                    summaryItems.push({
                        blockType: blockType,
                        label: label,
                        icon: icon,
                        count: count
                    });
                }
            });

            // Build popover HTML
            var totalCount = parseInt($badge.find('.count-value').text(), 10) || 0;
            var popoverHtml = '<div class="target-preview-popover total-preview-popover">';
            popoverHtml += '<div class="preview-popover-header">';
            popoverHtml += '<span class="preview-popover-title">' + (trans.total_summary || 'Selection Summary') + '</span>';
            popoverHtml += '<span class="preview-popover-count">' + totalCount + ' ' + (trans.total_items || 'total items') + '</span>';
            popoverHtml += '</div>';
            popoverHtml += '<div class="preview-popover-body">';
            popoverHtml += '<ul class="total-summary-list">';

            for (var i = 0; i < summaryItems.length; i++) {
                var item = summaryItems[i];
                popoverHtml += '<li class="total-summary-item" data-block-type="' + item.blockType + '">';
                popoverHtml += this.esIcon(item.icon);
                popoverHtml += '<span class="summary-item-label">' + self.escapeHtml(item.label) + '</span>';
                popoverHtml += '<span class="summary-item-count">' + item.count + '</span>';
                popoverHtml += '</li>';
            }

            popoverHtml += '</ul>';
            popoverHtml += '</div>';
            popoverHtml += '</div>';

            var $popover = $(popoverHtml);
            this.$previewPopover = $popover;

            // Click on item to switch to that tab
            $popover.on('click', '.total-summary-item', function() {
                var blockType = $(this).data('blockType');
                self.hidePreviewPopover();
                self.switchToBlock(blockType);
            });

            // Position popover
            $('body').append($popover);
            var badgeOffset = $badge.offset();
            var badgeHeight = $badge.outerHeight();
            var popoverWidth = $popover.outerWidth();

            $popover.css({
                position: 'absolute',
                top: badgeOffset.top + badgeHeight + 5,
                left: badgeOffset.left - (popoverWidth / 2) + ($badge.outerWidth() / 2),
                zIndex: 10000
            });

            // Adjust if off screen
            var windowWidth = $(window).width();
            var popoverRight = $popover.offset().left + popoverWidth;
            if (popoverRight > windowWidth - 10) {
                $popover.css('left', windowWidth - popoverWidth - 10);
            }
            if ($popover.offset().left < 10) {
                $popover.css('left', 10);
            }

            $popover.hide().fadeIn(150);
        },

        // =========================================================================
        // HOLIDAY PREVIEW (Country chip eye button click)
        // =========================================================================

        /**
         * Show holiday preview popover for a country
         * @param {number} countryId - Country ID
         * @param {string} countryName - Country name
         * @param {string} countryIso - Country ISO code
         * @param {jQuery} $trigger - The button element that triggered this
         */
        showHolidayPreview: function(countryId, countryName, countryIso, $trigger) {
            var self = this;
            var trans = this.config.trans || {};

            // Close any existing holiday popover
            $('.holiday-preview-popover').remove();

            // Create popover HTML
            var popoverHtml = '<div class="holiday-preview-popover target-preview-popover show">';
            popoverHtml += '<div class="popover-header">';
            popoverHtml += '<span class="popover-title">';
            if (countryIso) {
                popoverHtml += '<img src="https://flagcdn.com/20x15/' + this.escapeAttr(countryIso.toLowerCase()) + '.png" alt="" class="popover-flag"> ';
            }
            popoverHtml += this.escapeHtml(countryName) + ' - ' + (trans.holidays || 'Holidays');
            popoverHtml += '</span>';
            popoverHtml += '<button type="button" class="popover-close">' + this.esIcon('close') + '</button>';
            popoverHtml += '</div>';
            popoverHtml += '<div class="popover-body">';
            popoverHtml += '<div class="holiday-preview-loading">' + this.esIcon('sync', 'es-spin') + ' ' + (trans.loading || 'Loading...') + '</div>';
            popoverHtml += '</div>';
            popoverHtml += '</div>';

            var $popover = $(popoverHtml);
            $('body').append($popover);

            // Position popover near the trigger button
            var triggerRect = $trigger[0].getBoundingClientRect();
            var scrollTop = $(window).scrollTop();
            var scrollLeft = $(window).scrollLeft();
            var popoverWidth = $popover.outerWidth();
            var popoverHeight = $popover.outerHeight();
            var windowWidth = $(window).width();
            var windowHeight = $(window).height();

            // Default: position below and to the right of the trigger
            var top = triggerRect.bottom + scrollTop + 8;
            var left = triggerRect.left + scrollLeft;

            // Adjust horizontal position if it goes off-screen
            if (left + popoverWidth > windowWidth - 10) {
                left = windowWidth - popoverWidth - 10;
            }
            if (left < 10) {
                left = 10;
            }

            // Adjust vertical position if it goes below viewport
            if (triggerRect.bottom + popoverHeight > windowHeight - 10) {
                // Position above the trigger instead
                top = triggerRect.top + scrollTop - popoverHeight - 8;
            }

            $popover.css({
                position: 'absolute',
                top: top,
                left: left,
                zIndex: 10001
            });

            // Close button handler
            $popover.find('.popover-close').on('click', function() {
                $popover.remove();
            });

            // Fetch holidays via AJAX
            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'getHolidaysPreview',
                    trait: 'EntitySelector',
                    id_country: countryId
                },
                success: function(response) {
                    if (response.success && response.holidays && response.holidays.length > 0) {
                        var listHtml = '<div class="holiday-list">';
                        for (var i = 0; i < response.holidays.length; i++) {
                            var h = response.holidays[i];
                            var typeClass = h.type ? 'holiday-type-' + h.type.toLowerCase().replace(/\s+/g, '-') : '';
                            listHtml += '<div class="holiday-item ' + typeClass + '">';
                            listHtml += '<div class="holiday-date">';
                            listHtml += '<span class="holiday-day">' + self.escapeHtml(h.date_formatted || h.date) + '</span>';
                            if (h.day_of_week) {
                                listHtml += '<span class="holiday-weekday">' + self.escapeHtml(h.day_of_week) + '</span>';
                            }
                            listHtml += '</div>';
                            listHtml += '<div class="holiday-info">';
                            listHtml += '<span class="holiday-name">' + self.escapeHtml(h.name) + '</span>';
                            if (h.type) {
                                listHtml += '<span class="holiday-type-badge">' + self.escapeHtml(h.type) + '</span>';
                            }
                            listHtml += '</div>';
                            listHtml += '</div>';
                        }
                        listHtml += '</div>';

                        if (response.total_count) {
                            listHtml += '<div class="holiday-preview-note">' + response.total_count + ' ' + (trans.upcoming_holidays || 'upcoming holidays') + '</div>';
                        }

                        $popover.find('.popover-body').html(listHtml);
                    } else {
                        var noDataHtml = '<div class="holiday-preview-empty">';
                        noDataHtml += self.esIcon('event_busy');
                        noDataHtml += '<p>' + (trans.no_holidays || 'No holidays found') + '</p>';
                        noDataHtml += '</div>';
                        $popover.find('.popover-body').html(noDataHtml);
                    }

                    // Re-adjust position after content loaded
                    var newPopoverHeight = $popover.outerHeight();
                    if (triggerRect.bottom + newPopoverHeight > windowHeight - 10) {
                        var newTop = triggerRect.top + scrollTop - newPopoverHeight - 8;
                        if (newTop > 10) {
                            $popover.css('top', newTop);
                        }
                    }
                },
                error: function() {
                    var errorHtml = '<div class="holiday-preview-empty">';
                    errorHtml += self.esIcon('error');
                    errorHtml += '<p>' + (trans.error_loading || 'Error loading holidays') + '</p>';
                    errorHtml += '</div>';
                    $popover.find('.popover-body').html(errorHtml);
                }
            });
        },

        // =========================================================================
        // COUNTRIES HOLIDAY PREVIEW (Condition badge for multiple countries)
        // =========================================================================

        /**
         * Show holiday preview popover for multiple selected countries
         * @param {jQuery} $badge - The condition-match-count badge element
         * @param {Array} countryIds - Array of country IDs
         */
        showCountriesHolidayPreview: function($badge, countryIds) {
            var self = this;
            var trans = this.config.trans || {};

            // Close any existing popovers
            this.hidePreviewPopover();
            $('.holiday-preview-popover').remove();

            // Create popover HTML with placeholder title (will update after AJAX)
            var popoverHtml = '<div class="holiday-preview-popover target-preview-popover show">';
            popoverHtml += '<div class="popover-header">';
            popoverHtml += '<span class="popover-title">' + this.esIcon('sync', 'es-spin') + ' ' + (trans.loading || 'Loading...') + '</span>';
            popoverHtml += '<button type="button" class="popover-close">' + this.esIcon('close') + '</button>';
            popoverHtml += '</div>';
            popoverHtml += '<div class="popover-filter">';
            popoverHtml += this.esIcon('search');
            popoverHtml += '<input type="text" class="holiday-filter-input" placeholder="' + (trans.filter_holidays || 'Filter by country, date, name...') + '">';
            popoverHtml += '</div>';
            popoverHtml += '<div class="popover-body">';
            popoverHtml += '<div class="holiday-preview-loading">' + this.esIcon('sync', 'es-spin') + ' ' + (trans.loading || 'Loading...') + '</div>';
            popoverHtml += '</div>';
            popoverHtml += '</div>';

            var $popover = $(popoverHtml);
            $('body').append($popover);

            // Position popover near the badge
            var badgeRect = $badge[0].getBoundingClientRect();
            var scrollTop = $(window).scrollTop();
            var scrollLeft = $(window).scrollLeft();
            var popoverWidth = $popover.outerWidth();
            var popoverHeight = $popover.outerHeight();
            var windowWidth = $(window).width();
            var windowHeight = $(window).height();

            // Default: position below the badge
            var top = badgeRect.bottom + scrollTop + 8;
            var left = badgeRect.left + scrollLeft;

            // Adjust horizontal position
            if (left + popoverWidth > windowWidth - 10) {
                left = windowWidth - popoverWidth - 10;
            }
            if (left < 10) {
                left = 10;
            }

            // Adjust vertical position if it goes below viewport
            if (badgeRect.bottom + popoverHeight > windowHeight - 10) {
                top = badgeRect.top + scrollTop - popoverHeight - 8;
            }

            $popover.css({
                position: 'absolute',
                top: top,
                left: left,
                zIndex: 10001
            });

            // Mark badge as open
            $badge.addClass('popover-open');
            this.$activeBadge = $badge;

            // Close button handler
            $popover.find('.popover-close').on('click', function() {
                $popover.remove();
                $badge.removeClass('popover-open');
                self.$activeBadge = null;
            });

            // Fetch holidays via AJAX
            $.ajax({
                url: this.config.ajaxUrl,
                type: 'POST',
                dataType: 'json',
                data: {
                    ajax: 1,
                    action: 'getHolidaysForCountries',
                    trait: 'EntitySelector',
                    country_ids: countryIds.join(','),
                    count_only: 0
                },
                success: function(response) {
                    if (response.success && response.holidays && response.holidays.length > 0) {
                        // Count holidays per country to determine which flags to show
                        var countryHolidayCounts = {};
                        var countriesMap = {};

                        // Build map of countries from response
                        if (response.countries) {
                            for (var ci = 0; ci < response.countries.length; ci++) {
                                var cInfo = response.countries[ci];
                                countriesMap[cInfo.id] = cInfo;
                                countryHolidayCounts[cInfo.id] = 0;
                            }
                        }

                        // Count holidays per country
                        for (var hi = 0; hi < response.holidays.length; hi++) {
                            var hol = response.holidays[hi];
                            if (hol.country_id && typeof countryHolidayCounts[hol.country_id] !== 'undefined') {
                                countryHolidayCounts[hol.country_id]++;
                            }
                        }

                        // Sort countries by holiday count (descending)
                        var sortedCountries = Object.keys(countriesMap).sort(function(a, b) {
                            return (countryHolidayCounts[b] || 0) - (countryHolidayCounts[a] || 0);
                        }).map(function(id) {
                            return countriesMap[id];
                        });

                        // Build header title with flags for countries with most holidays
                        var titleHtml = '';
                        var numCountries = sortedCountries.length;
                        if (numCountries <= 3) {
                            for (var fi = 0; fi < numCountries; fi++) {
                                var fc = sortedCountries[fi];
                                if (fc && fc.iso_code) {
                                    titleHtml += '<img src="https://flagcdn.com/20x15/' + self.escapeAttr(fc.iso_code.toLowerCase()) + '.png" alt="' + self.escapeAttr(fc.iso_code) + '" class="popover-flag" title="' + self.escapeAttr(fc.name) + '"> ';
                                }
                            }
                        } else {
                            // Show top 2 flags (countries with most holidays) + count
                            for (var fj = 0; fj < 2; fj++) {
                                var fcc = sortedCountries[fj];
                                if (fcc && fcc.iso_code) {
                                    titleHtml += '<img src="https://flagcdn.com/20x15/' + self.escapeAttr(fcc.iso_code.toLowerCase()) + '.png" alt="" class="popover-flag" title="' + self.escapeAttr(fcc.name) + '"> ';
                                }
                            }
                            titleHtml += '+' + (numCountries - 2) + ' ';
                        }
                        titleHtml += response.total_count + ' ' + (trans.holidays || 'Holidays');

                        // Update header title
                        $popover.find('.popover-title').html(titleHtml);

                        var listHtml = '<div class="holiday-list">';
                        for (var i = 0; i < response.holidays.length; i++) {
                            var h = response.holidays[i];
                            var typeClass = h.type ? 'holiday-type-' + h.type.toLowerCase().replace(/\s+/g, '-') : '';
                            // Build search text for filtering
                            var searchText = [
                                h.name || '',
                                h.date_formatted || h.date || '',
                                h.day_of_week || '',
                                h.country_name || '',
                                h.type || ''
                            ].join(' ').toLowerCase();
                            listHtml += '<div class="holiday-item ' + typeClass + '" data-search="' + self.escapeAttr(searchText) + '">';
                            listHtml += '<div class="holiday-date">';
                            listHtml += '<span class="holiday-day">' + self.escapeHtml(h.date_formatted || h.date) + '</span>';
                            if (h.day_of_week) {
                                listHtml += '<span class="holiday-weekday">' + self.escapeHtml(h.day_of_week) + '</span>';
                            }
                            listHtml += '</div>';
                            listHtml += '<div class="holiday-info">';
                            // Show country flag before holiday name when multiple countries
                            if (h.country_iso && countryIds.length > 1) {
                                listHtml += '<img src="https://flagcdn.com/16x12/' + self.escapeAttr(h.country_iso.toLowerCase()) + '.png" alt="" class="holiday-country-flag" title="' + self.escapeAttr(h.country_name || '') + '"> ';
                            }
                            listHtml += '<span class="holiday-name">' + self.escapeHtml(h.name) + '</span>';
                            if (h.type) {
                                listHtml += '<span class="holiday-type-badge">' + self.escapeHtml(h.type) + '</span>';
                            }
                            listHtml += '</div>';
                            listHtml += '</div>';
                        }
                        listHtml += '</div>';

                        if (response.total_count && countryIds.length > 1) {
                            var noteText = (trans.across_countries || 'across') + ' ' + countryIds.length + ' ' + (trans.countries || 'countries');
                            listHtml += '<div class="holiday-preview-note">' + noteText + '</div>';
                        }

                        $popover.find('.popover-body').html(listHtml);

                        // Setup filter input handler
                        $popover.find('.holiday-filter-input').on('input', function() {
                            var query = $(this).val().toLowerCase().trim();
                            var $items = $popover.find('.holiday-item');
                            var visibleCount = 0;

                            $items.each(function() {
                                var searchData = $(this).attr('data-search') || '';
                                if (!query || searchData.indexOf(query) !== -1) {
                                    $(this).show();
                                    visibleCount++;
                                } else {
                                    $(this).hide();
                                }
                            });

                            // Update note with filtered count
                            var $note = $popover.find('.holiday-preview-note');
                            if (query && $note.length) {
                                $note.text(visibleCount + ' ' + (trans.matches || 'matches'));
                            } else if ($note.length && countryIds.length > 1) {
                                var noteText = (trans.across_countries || 'across') + ' ' + countryIds.length + ' ' + (trans.countries || 'countries');
                                $note.text(noteText);
                            }
                        });
                    } else {
                        // Update header for empty state
                        $popover.find('.popover-title').html('0 ' + (trans.holidays || 'Holidays'));

                        var noDataHtml = '<div class="holiday-preview-empty">';
                        noDataHtml += self.esIcon('event_busy');
                        noDataHtml += '<p>' + (trans.no_holidays || 'No holidays found') + '</p>';
                        noDataHtml += '</div>';
                        $popover.find('.popover-body').html(noDataHtml);
                    }

                    // Re-adjust position after content loaded
                    var newPopoverHeight = $popover.outerHeight();
                    if (badgeRect.bottom + newPopoverHeight > windowHeight - 10) {
                        var newTop = badgeRect.top + scrollTop - newPopoverHeight - 8;
                        if (newTop > 10) {
                            $popover.css('top', newTop);
                        }
                    }
                },
                error: function() {
                    // Update header for error state
                    $popover.find('.popover-title').html(self.esIcon('error') + ' ' + (trans.error || 'Error'));

                    var errorHtml = '<div class="holiday-preview-empty">';
                    errorHtml += self.esIcon('error');
                    errorHtml += '<p>' + (trans.error_loading || 'Error loading holidays') + '</p>';
                    errorHtml += '</div>';
                    $popover.find('.popover-body').html(errorHtml);
                }
            });
        }
    };

})(jQuery);
