/**
 * Entity Selector - Events Module
 * All event binding and handlers
 * @partial _events.js
 *
 * Contains event handlers for:
 * - Tab switching
 * - Block/group collapse toggle
 * - Dropdown open/close
 * - Search input handling
 * - Item selection/deselection
 * - Group add/remove
 * - Exclude row add/remove
 * - Method select changes
 * - Filter panel toggles
 * - Keyboard shortcuts (Ctrl+A, Ctrl+D, Esc, Enter)
 * - Load more pagination
 * - Sort controls
 * - View mode switching
 * - Tree view events
 * - Preview badge clicks
 * - Pattern tag interactions
 * - Combination picker events
 * - Group modifier events
 */

(function($) {
    'use strict';

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

    window._EntitySelectorMixins.events = {

        bindEvents: function() {
            var self = this;

            // Tab switching
            this.$wrapper.on('click', '.target-block-tab', function(e) {
                e.preventDefault();
                var blockType = $(this).data('blockType');
                self.switchToBlock(blockType);
            });

            // Tab badge click for preview popover (toggle)
            this.$wrapper.on('click', '.target-block-tab .tab-badge', function(e) {
                e.stopPropagation();
                e.preventDefault();

                var $tab = $(this).closest('.target-block-tab');
                var $badge = $(this);

                if ($badge.hasClass('popover-open')) {
                    self.hidePreviewPopover();
                } else {
                    self.showPreviewPopover($tab);
                }
            });

            // Condition count badge click for preview popover
            this.$wrapper.on('click', '.condition-match-count.clickable', function(e) {
                e.stopPropagation();
                e.preventDefault();

                var $badge = $(this);

                if ($badge.hasClass('popover-open')) {
                    self.hidePreviewPopover();
                } else {
                    self.showConditionPreviewPopover($badge);
                }
            });

            // Group count badge click for preview popover
            this.$wrapper.on('click', '.group-count-badge.clickable', function(e) {
                e.stopPropagation();
                e.preventDefault();

                var $badge = $(this);

                if ($badge.hasClass('popover-open')) {
                    self.hidePreviewPopover();
                } else {
                    self.showGroupPreviewPopover($badge);
                }
            });

            // Total count badge click for summary popover
            this.$wrapper.on('click', '.trait-total-count', function(e) {
                e.stopPropagation();
                e.preventDefault();

                var $badge = $(this);

                if ($badge.hasClass('popover-open')) {
                    self.hidePreviewPopover();
                } else {
                    self.showTotalPreviewPopover($badge);
                }
            });

            // Close popover when clicking outside
            $(document).on('click', function(e) {
                if (!$(e.target).closest('.target-preview-popover').length &&
                    !$(e.target).closest('.holiday-preview-popover').length &&
                    !$(e.target).closest('.tab-badge').length &&
                    !$(e.target).closest('.condition-match-count').length &&
                    !$(e.target).closest('.group-count-badge').length &&
                    !$(e.target).closest('.group-modifiers').length &&
                    !$(e.target).closest('.group-preview-badge').length &&
                    !$(e.target).closest('.toggle-count.clickable').length &&
                    !$(e.target).closest('.trait-total-count').length &&
                    !$(e.target).closest('.chip-preview-holidays').length) {
                    self.hidePreviewPopover();
                    // Also close holiday popover
                    $('.holiday-preview-popover').remove();
                }
            });

            // Block-level collapse toggle (click on header)
            this.$wrapper.on('click', '.condition-trait-header', function(e) {
                if ($(e.target).closest('.target-block-tabs').length ||
                    $(e.target).closest('.trait-header-actions').length ||
                    $(e.target).closest('.prestashop-switch').length ||
                    $(e.target).closest('.trait-total-count').length) {
                    return;
                }
                var $body = self.$wrapper.find('.condition-trait-body');
                $body.stop(true, true);
                if ($body.is(':visible')) {
                    $body.slideUp(200);
                    self.$wrapper.addClass('collapsed');
                } else {
                    $body.slideDown(200);
                    self.$wrapper.removeClass('collapsed');
                }
            });

            // Toggle blocks content (form-content layout)
            this.$wrapper.on('click', '.btn-toggle-blocks', function(e) {
                e.preventDefault();
                var $blocksContent = self.$wrapper.find('.entity-selector-blocks-content');
                var $icon = $(this).find('.es-icon');
                $blocksContent.stop(true, true);
                if ($blocksContent.is(':visible')) {
                    $blocksContent.slideUp(200);
                    self.$wrapper.addClass('blocks-collapsed');
                    $icon.text('expand_more');
                } else {
                    $blocksContent.slideDown(200);
                    self.$wrapper.removeClass('blocks-collapsed');
                    $icon.text('expand_less');
                }
            });

            // Custom block input changes — update tab badge when value changes
            this.$wrapper.on('input change', '.custom-block-content input, .custom-block-content textarea, .custom-block-content select', function() {
                self.updateTabBadges();
            });

            // Group-level collapse toggle (click on group header or toggle icon)
            this.$wrapper.on('click', '.group-header', function(e) {
                if ($(e.target).closest('.btn-remove-group, .group-name-input').length) {
                    return;
                }
                if (self.$wrapper.data('mode') === 'single') {
                    return;
                }
                var $group = $(this).closest('.selection-group');
                $group.toggleClass('collapsed');
            });

            // Toggle all groups (single button that switches between expand/collapse)
            console.log('[ES-DEBUG] Binding .btn-toggle-groups click on wrapper:', self.$wrapper.attr('id'), 'found buttons:', self.$wrapper.find('.btn-toggle-groups').length);
            this.$wrapper.on('click', '.btn-toggle-groups', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $btn = $(this);
                var currentState = $btn.attr('data-state') || 'collapsed';
                var trans = self.config.trans || {};
                console.log('[ES-DEBUG] .btn-toggle-groups CLICKED! currentState:', currentState, 'btn parent:', $btn.parent().attr('class'), 'groups found:', self.$wrapper.find('.selection-group').length);

                if (currentState === 'collapsed') {
                    self.$wrapper.find('.selection-group').removeClass('collapsed');
                    $btn.attr('data-state', 'expanded');
                    $btn.attr('title', trans.collapse_all || 'Collapse all groups');
                    $btn.find('i').text('close_fullscreen');
                    console.log('[ES-DEBUG] Expanded all groups');
                } else {
                    self.$wrapper.find('.selection-group').addClass('collapsed');
                    $btn.attr('data-state', 'collapsed');
                    $btn.attr('title', trans.expand_all || 'Expand all groups');
                    $btn.find('i').text('open_in_full');
                    console.log('[ES-DEBUG] Collapsed all groups');
                }
            });

            // Show all toggle change (legacy checkbox)
            this.$wrapper.on('change', '.trait-show-all-toggle .show-all-checkbox', function(e) {
                e.stopPropagation();
                var isChecked = $(this).prop('checked');
                if (isChecked) {
                    self.clearAllConditions();
                }
            });

            // Target switch change (PrestaShop native switch)
            this.$wrapper.on('change', '.target-switch-toggle', function(e) {
                e.stopPropagation();
                var value = $(this).val();
                if (value === '1') {
                    self.clearAllConditions();
                    self.$wrapper.find('.condition-trait-body').slideUp(200);
                    self.$wrapper.addClass('collapsed');
                } else {
                    self.$wrapper.find('.condition-trait-body').slideDown(200);
                    self.$wrapper.removeClass('collapsed');
                }
            });

            // Add group
            this.$wrapper.on('click', '.btn-add-group', function(e) {
                e.preventDefault();
                var $block = $(this).closest('.target-block');
                var blockType = $block.data('blockType');
                self.addGroup($block, blockType);
            });

            // Remove group
            this.$wrapper.on('click', '.btn-remove-group', function(e) {
                e.preventDefault();
                var $group = $(this).closest('.selection-group');
                var $block = $(this).closest('.target-block');
                self.removeGroup($group, $block);
            });

            // Group name input - stop propagation to prevent collapse
            this.$wrapper.on('click focus', '.group-name-input', function(e) {
                e.stopPropagation();
            });

            // Group name change
            this.$wrapper.on('change blur', '.group-name-input', function() {
                var $input = $(this);
                var $group = $input.closest('.selection-group');
                var name = $.trim($input.val());
                $group.attr('data-group-name', name);
                self.serializeAllBlocks();
            });

            // Add exceptions (first exclude row)
            this.$wrapper.on('click', '.btn-add-exclude', function(e) {
                e.preventDefault();
                var $group = $(this).closest('.selection-group');
                var $block = $(this).closest('.target-block');
                self.addFirstExcludeRow($group, $block);
            });

            // Add another exclude row
            this.$wrapper.on('click', '.btn-add-another-exclude', function(e) {
                e.preventDefault();
                var $group = $(this).closest('.selection-group');
                var $block = $(this).closest('.target-block');
                self.addExcludeRow($group, $block);
            });

            // Remove individual exclude row
            this.$wrapper.on('click', '.btn-remove-exclude-row', function(e) {
                e.preventDefault();
                var $excludeRow = $(this).closest('.exclude-row');
                var $group = $(this).closest('.selection-group');
                var $block = $(this).closest('.target-block');
                self.removeExcludeRow($excludeRow, $group, $block);
            });

            // Include method change
            this.$wrapper.on('change', '.include-method-select', function() {
                self.hideDropdown();

                var $group = $(this).closest('.selection-group');
                var $block = $(this).closest('.target-block');
                var $row = $group.find('.group-include');
                var blockType = $block.data('blockType');
                var blockDef = self.config.blocks[blockType] || {};
                var methods = blockDef.selection_methods || {};

                var $option = $(this).find('option:selected');
                var valueType = $option.data('valueType') || 'none';
                var searchEntity = $option.data('searchEntity') || '';
                var methodOptions = $option.data('options') || null;

                var $oldPicker = $group.find('.include-picker');
                var newPickerHtml = self.buildValuePickerHtml('include', valueType, searchEntity, methods);
                $oldPicker.replaceWith(newPickerHtml);

                if (valueType === 'select' && methodOptions) {
                    var $newPicker = $group.find('.include-picker');
                    var $select = $newPicker.find('.select-value-input');
                    $select.empty();
                    $.each(methodOptions, function(key, label) {
                        $select.append('<option value="' + self.escapeAttr(key) + '">' + self.escapeHtml(label) + '</option>');
                    });
                }

                if (valueType === 'multi_select_tiles' && methodOptions) {
                    var $newPicker = $group.find('.include-picker');
                    var isExclusive = $option.data('exclusive') === true;
                    self.populateTiles($newPicker, methodOptions, isExclusive);
                }

                if (valueType === 'multi_numeric_range') {
                    var $newPicker = $group.find('.include-picker');
                    var step = $option.data('step');
                    var min = $option.data('min');
                    self.applyRangeInputConstraints($newPicker, step, min);
                }

                if (valueType === 'combination_attributes') {
                    var $newPicker = $group.find('.include-picker');
                    self.loadCombinationAttributeGroups($newPicker);
                }

                var selectedMethod = $(this).val();
                self.updateMethodInfoPlaceholder($group.find('.method-selector-wrapper'), selectedMethod, blockType);

                self.updateBlockStatus($block);
                self.serializeAllBlocks($row);
            });

            // Exclude method change (within an exclude row)
            this.$wrapper.on('change', '.exclude-method-select', function() {
                self.hideDropdown();

                var $excludeRow = $(this).closest('.exclude-row');
                var $group = $(this).closest('.selection-group');
                var $block = $(this).closest('.target-block');
                var blockType = $block.data('blockType');
                var blockDef = self.config.blocks[blockType] || {};
                var methods = blockDef.selection_methods || {};

                var $option = $(this).find('option:selected');
                var valueType = $option.data('valueType') || 'entity_search';
                var searchEntity = $option.data('searchEntity') || blockType;
                var methodOptions = $option.data('options') || null;

                var $oldPicker = $excludeRow.find('.exclude-picker');
                var newPickerHtml = self.buildValuePickerHtml('exclude', valueType, searchEntity, methods);
                $oldPicker.replaceWith(newPickerHtml);

                if (valueType === 'select' && methodOptions) {
                    var $newPicker = $excludeRow.find('.exclude-picker');
                    var $select = $newPicker.find('.select-value-input');
                    $select.empty();
                    $.each(methodOptions, function(key, label) {
                        $select.append('<option value="' + self.escapeAttr(key) + '">' + self.escapeHtml(label) + '</option>');
                    });
                }

                if (valueType === 'multi_select_tiles' && methodOptions) {
                    var $newPicker = $excludeRow.find('.exclude-picker');
                    var isExclusive = $option.data('exclusive') === true;
                    self.populateTiles($newPicker, methodOptions, isExclusive);
                }

                if (valueType === 'multi_numeric_range') {
                    var $newPicker = $excludeRow.find('.exclude-picker');
                    var step = $option.data('step');
                    var min = $option.data('min');
                    self.applyRangeInputConstraints($newPicker, step, min);
                }

                if (valueType === 'combination_attributes') {
                    var $newPicker = $excludeRow.find('.exclude-picker');
                    self.loadCombinationAttributeGroups($newPicker);
                }

                var selectedMethod = $(this).val();
                self.updateMethodInfoPlaceholder($excludeRow.find('.exclude-header-row'), selectedMethod, blockType);

                self.serializeAllBlocks($excludeRow);
            });

            // Handle pattern input Enter key - adds pattern as tag
            this.$wrapper.on('keydown', '.pattern-input', function(e) {
                if (e.keyCode === 13) {
                    e.preventDefault();
                    var $btn = $(this).closest('.draft-tag').find('.btn-add-pattern');
                    $btn.click();
                }
            });

            // Handle add pattern button click (in draft tag)
            this.$wrapper.on('click', '.draft-tag .btn-add-pattern', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $draftTag = $(this).closest('.draft-tag');
                var $picker = $draftTag.closest('.value-picker');
                var $row = $draftTag.closest('.group-include, .exclude-row');
                var $input = $draftTag.find('.pattern-input');
                var pattern = $.trim($input.val());

                if (pattern) {
                    var caseSensitive = $draftTag.attr('data-case-sensitive') === '1';
                    self.addPatternTag($picker, pattern, caseSensitive);

                    $input.val('').focus();
                    $draftTag.find('.pattern-match-count').removeClass('count-found count-zero').hide();
                    $draftTag.find('.pattern-match-count .count-value').text('');

                    self.serializeAllBlocks($row);
                }
            });

            // Handle pattern input live typing - update match count in draft tag
            this.$wrapper.on('input', '.pattern-input', function() {
                var $input = $(this);
                var $draftTag = $input.closest('.draft-tag');
                if (!$draftTag.length) return;

                var pattern = $.trim($input.val());

                if ($input.data('countTimeout')) {
                    clearTimeout($input.data('countTimeout'));
                }

                var $matchCount = $draftTag.find('.pattern-match-count');

                if (!pattern) {
                    $matchCount.removeClass('count-found count-zero').hide();
                    $matchCount.find('.count-value').text('');
                    var $group = $draftTag.closest('.selection-group');
                    if ($group.length) {
                        self.updateGroupTotalCount($group);
                    }
                    return;
                }

                var timeout = setTimeout(function() {
                    var caseSensitive = $draftTag.attr('data-case-sensitive') === '1';
                    self.updateDraftTagCount($draftTag, pattern, caseSensitive);
                }, 300);
                $input.data('countTimeout', timeout);
            });

            // Handle pattern tag remove
            this.$wrapper.on('click', '.pattern-tag .btn-remove-pattern', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $row = $(this).closest('.group-include, .exclude-row');
                $(this).closest('.pattern-tag').remove();
                self.serializeAllBlocks($row);
            });

            // Handle pattern tag case-sensitivity toggle
            this.$wrapper.on('click', '.pattern-tag .btn-toggle-case', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $tag = $(this).closest('.pattern-tag');
                var $btn = $(this);
                var trans = self.config.trans || {};
                var isDraftTag = $tag.hasClass('draft-tag');

                var isCaseSensitive = $tag.data('caseSensitive') === 1 || $tag.data('caseSensitive') === '1' || $tag.attr('data-case-sensitive') === '1';
                var newCaseSensitive = !isCaseSensitive;

                $tag.data('caseSensitive', newCaseSensitive ? 1 : 0);
                $tag.attr('data-case-sensitive', newCaseSensitive ? '1' : '0');
                $tag.toggleClass('case-sensitive', newCaseSensitive);

                $btn.find('.case-icon').text(newCaseSensitive ? 'Aa' : 'aa');
                var caseTitle = newCaseSensitive
                    ? (trans.case_sensitive || 'Case sensitive - click to toggle')
                    : (trans.case_insensitive || 'Case insensitive - click to toggle');
                $btn.attr('title', caseTitle);

                if (isDraftTag) {
                    var pattern = $.trim($tag.find('.pattern-input').val());
                    if (pattern) {
                        self.updateDraftTagCount($tag, pattern, newCaseSensitive);
                    }
                } else {
                    var $row = $tag.closest('.group-include, .exclude-row');
                    self.serializeAllBlocks($row);
                }
            });

            // Handle pattern match count click - show preview modal
            this.$wrapper.on('click', '.pattern-match-count', function(e) {
                e.preventDefault();
                e.stopPropagation();

                var $matchCount = $(this);
                var count = $matchCount.data('count');
                var pattern = $matchCount.data('pattern');
                var entityType = $matchCount.data('entityType');
                var caseSensitive = $matchCount.data('caseSensitive');

                if (!count || count <= 0 || !pattern) {
                    return;
                }

                self.showPatternPreviewModal(pattern, entityType, caseSensitive, count);
            });

            // Handle pattern tag edit (click on tag text)
            this.$wrapper.on('click', '.pattern-tag .pattern-tag-text', function(e) {
                e.preventDefault();
                var $tag = $(this).closest('.pattern-tag');
                if ($tag.hasClass('editing')) return;

                var currentPattern = $tag.data('pattern');

                var $editInput = $('<input type="text" class="pattern-tag-edit">').val(currentPattern);
                var $saveBtn = $('<button type="button" class="btn-pattern-save" title="Save">' + this.esIcon('check') + '</button>');
                var $cancelBtn = $('<button type="button" class="btn-pattern-cancel" title="Cancel">' + this.esIcon('close') + '</button>');
                var $editActions = $('<span class="pattern-edit-actions"></span>').append($saveBtn, $cancelBtn);

                $tag.addClass('editing').find('.pattern-tag-text').hide();
                $tag.find('.btn-remove-pattern').hide();
                $tag.prepend($editActions).prepend($editInput);
                $editInput.focus().select();

                $editInput.on('keydown', function(ev) {
                    if (ev.keyCode === 13) {
                        ev.preventDefault();
                        $saveBtn.click();
                    } else if (ev.keyCode === 27) {
                        ev.preventDefault();
                        $cancelBtn.click();
                    }
                });
            });

            // Pattern edit - Save button
            this.$wrapper.on('click', '.pattern-tag .btn-pattern-save', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $tag = $(this).closest('.pattern-tag');
                var $editInput = $tag.find('.pattern-tag-edit');
                var currentPattern = $tag.data('pattern');
                var newPattern = $.trim($editInput.val());

                if (newPattern && newPattern !== currentPattern) {
                    $tag.data('pattern', newPattern);
                    $tag.find('.pattern-tag-text').text(newPattern);
                }
                $editInput.remove();
                $tag.find('.pattern-edit-actions').remove();
                $tag.removeClass('editing').find('.pattern-tag-text, .btn-remove-pattern').show();
                var $row = $tag.closest('.group-include, .exclude-row');
                self.serializeAllBlocks($row);
            });

            // Pattern edit - Cancel button
            this.$wrapper.on('click', '.pattern-tag .btn-pattern-cancel', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $tag = $(this).closest('.pattern-tag');
                $tag.find('.pattern-tag-edit').remove();
                $tag.find('.pattern-edit-actions').remove();
                $tag.removeClass('editing').find('.pattern-tag-text, .btn-remove-pattern').show();
            });

            // Handle numeric range input changes
            this.$wrapper.on('change', '.range-min-input, .range-max-input', function() {
                var $row = $(this).closest('.group-include, .exclude-row');
                self.serializeAllBlocks($row);
            });

            // Handle date range input changes
            this.$wrapper.on('change', '.date-from-input, .date-to-input', function() {
                var $row = $(this).closest('.group-include, .exclude-row');
                self.serializeAllBlocks($row);
            });

            // Handle select value changes
            this.$wrapper.on('change', '.select-value-input', function() {
                var $row = $(this).closest('.group-include, .exclude-row');
                self.serializeAllBlocks($row);
            });

            // Handle multi-range add button click
            this.$wrapper.on('click', '.btn-add-range', function(e) {
                e.preventDefault();
                var $picker = $(this).closest('.value-picker');
                var $row = $(this).closest('.group-include, .exclude-row');
                var $container = $picker.find('.multi-range-container');
                var $chipsContainer = $container.find('.multi-range-chips');
                var $minInput = $container.find('.range-min-input');
                var $maxInput = $container.find('.range-max-input');

                var minVal = $minInput.val().trim();
                var maxVal = $maxInput.val().trim();

                if (minVal === '' && maxVal === '') {
                    return;
                }

                var step = parseFloat($minInput.attr('step')) || 0.01;
                var minAllowed = $minInput.attr('min');
                var hasMinConstraint = typeof minAllowed !== 'undefined' && minAllowed !== '';
                minAllowed = hasMinConstraint ? parseFloat(minAllowed) : null;

                var minNum = minVal !== '' ? parseFloat(minVal) : null;
                var maxNum = maxVal !== '' ? parseFloat(maxVal) : null;

                if (hasMinConstraint) {
                    if (minNum !== null && minNum < minAllowed) {
                        self.showRangeInputError($minInput, self.config.trans.min_value_error || 'Minimum value is ' + minAllowed);
                        return;
                    }
                    if (maxNum !== null && maxNum < minAllowed) {
                        self.showRangeInputError($maxInput, self.config.trans.min_value_error || 'Minimum value is ' + minAllowed);
                        return;
                    }
                }

                if (minNum !== null && maxNum !== null && minNum > maxNum) {
                    self.showRangeInputError($minInput, self.config.trans.min_greater_than_max || 'Min cannot be greater than max');
                    return;
                }

                var decimals = step < 1 ? String(step).split('.')[1].length : 0;
                if (minNum !== null) {
                    if (step >= 1) {
                        minNum = Math.round(minNum);
                    } else {
                        minNum = parseFloat(minNum.toFixed(decimals));
                    }
                    minVal = String(minNum);
                }
                if (maxNum !== null) {
                    if (step >= 1) {
                        maxNum = Math.round(maxNum);
                    } else {
                        maxNum = parseFloat(maxNum.toFixed(decimals));
                    }
                    maxVal = String(maxNum);
                }

                var chipText = '';
                if (minVal !== '' && maxVal !== '') {
                    chipText = minVal + ' - ' + maxVal;
                } else if (minVal !== '') {
                    chipText = '≥ ' + minVal;
                } else {
                    chipText = '≤ ' + maxVal;
                }

                var $chip = $('<span>', {
                    class: 'range-chip',
                    'data-min': minVal,
                    'data-max': maxVal
                });
                $chip.append($('<span>', { class: 'range-chip-text', text: chipText }));
                $chip.append($('<button>', {
                    type: 'button',
                    class: 'btn-remove-range',
                    html: self.esIcon('close')
                }));

                $chipsContainer.append($chip);

                $minInput.val('');
                $maxInput.val('');

                self.serializeAllBlocks($row);
            });

            // Handle multi-range chip removal
            this.$wrapper.on('click', '.btn-remove-range', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $chip = $(this).closest('.range-chip');
                var $row = $chip.closest('.group-include, .exclude-row');
                $chip.remove();
                self.serializeAllBlocks($row);
            });

            // Handle Enter key in multi-range inputs
            this.$wrapper.on('keydown', '.multi-range-container .range-min-input, .multi-range-container .range-max-input', function(e) {
                if (e.keyCode === 13) {
                    e.preventDefault();
                    $(this).closest('.multi-range-container').find('.btn-add-range').click();
                }
            });

            // Handle multi-select tile clicks
            this.$wrapper.on('click', '.tile-option', function(e) {
                e.preventDefault();
                var $tile = $(this);
                var $container = $tile.closest('.multi-select-tiles');
                var $row = $tile.closest('.group-include, .exclude-row');
                var isExclusive = $container.attr('data-exclusive') === 'true';

                if (isExclusive) {
                    if ($tile.hasClass('selected')) {
                        $tile.removeClass('selected');
                    } else {
                        $container.find('.tile-option').removeClass('selected');
                        $tile.addClass('selected');
                    }
                } else {
                    $tile.toggleClass('selected');
                }

                self.serializeAllBlocks($row);
            });

            // Handle combination attribute value toggle
            this.$wrapper.on('click', '.comb-attr-value', function(e) {
                e.preventDefault();
                var $value = $(this);
                var $row = $value.closest('.group-include, .exclude-row');
                var $picker = $value.closest('.value-picker');

                $value.toggleClass('selected');
                self.updateCombinationData($picker);
                self.serializeAllBlocks($row);
            });

            // Handle combination mode toggle
            this.$wrapper.on('change', '.comb-mode-radio', function() {
                var $picker = $(this).closest('.value-picker');
                var $row = $(this).closest('.group-include, .exclude-row');
                self.updateCombinationData($picker);
                self.serializeAllBlocks($row);
            });

            // Handle combination select all
            this.$wrapper.on('click', '.comb-select-all', function(e) {
                e.preventDefault();
                var $group = $(this).closest('.comb-attr-group');
                var $picker = $(this).closest('.value-picker');
                var $row = $(this).closest('.group-include, .exclude-row');
                $group.find('.comb-attr-value:visible').addClass('selected');
                self.updateCombinationData($picker);
                self.serializeAllBlocks($row);
            });

            // Handle combination select none
            this.$wrapper.on('click', '.comb-select-none', function(e) {
                e.preventDefault();
                var $group = $(this).closest('.comb-attr-group');
                var $picker = $(this).closest('.value-picker');
                var $row = $(this).closest('.group-include, .exclude-row');
                $group.find('.comb-attr-value').removeClass('selected');
                self.updateCombinationData($picker);
                self.serializeAllBlocks($row);
            });

            // Handle combination attribute search/filter
            this.$wrapper.on('input', '.comb-attr-search', function() {
                var query = $(this).val().toLowerCase().trim();
                var $group = $(this).closest('.comb-attr-group');
                $group.find('.comb-attr-value').each(function() {
                    var name = $(this).data('name') || '';
                    if (!query || name.indexOf(query) !== -1) {
                        $(this).show();
                    } else {
                        $(this).hide();
                    }
                });
            });

            // Handle group-level modifier toggle
            this.$wrapper.on('click', '.btn-toggle-modifiers', function(e) {
                e.preventDefault();
                var $btn = $(this);
                var $modifiers = $btn.closest('.group-modifiers');
                var $content = $modifiers.find('.group-modifiers-content');
                $content.slideToggle(150, function() {
                    $modifiers.toggleClass('expanded', $content.is(':visible'));
                });
            });

            // Handle group-level modifier changes
            this.$wrapper.on('change input', '.group-modifier-limit', function() {
                var $group = $(this).closest('.selection-group');
                var $limitInput = $(this);
                var limit = parseInt($limitInput.val(), 10);
                var $badge = $group.find('.group-header .group-count-badge');
                var finalCount = $badge.data('finalCount') || 0;

                var $previewBadge = $group.find('.group-preview-badge .preview-count');
                if ($previewBadge.length && finalCount > 0) {
                    var displayCount = (limit > 0 && limit < finalCount) ? limit : finalCount;
                    $previewBadge.text(displayCount);
                }

                self.updateModifierButtonState($group);
                self.serializeAllBlocks();
                self.refreshGroupPreviewIfOpen($group);
            });

            // Sort dropdown change
            this.$wrapper.on('change', '.group-modifier-sort', function() {
                var $group = $(this).closest('.selection-group');
                self.serializeAllBlocks();
                self.refreshGroupPreviewIfOpen($group);
            });

            // Sort direction button click
            this.$wrapper.on('click', '.group-modifiers .btn-sort-dir', function(e) {
                e.preventDefault();
                var $btn = $(this);
                var $group = $btn.closest('.selection-group');
                var currentDir = $btn.data('dir') || 'DESC';
                var newDir = (currentDir === 'DESC') ? 'ASC' : 'DESC';

                $btn.data('dir', newDir);
                $btn.attr('data-dir', newDir);

                var $icon = $btn.find('i');
                $icon.replaceWith(this.esIcon('sort'));

                self.serializeAllBlocks();
                self.refreshGroupPreviewIfOpen($group);
            });

            // Group preview badge click
            this.$wrapper.on('click', '.group-preview-badge.clickable', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $badge = $(this);
                var $group = $badge.closest('.selection-group');
                var $block = $badge.closest('.target-block');
                var blockType = $block.data('blockType');

                if ($badge.hasClass('popover-open')) {
                    self.hidePreviewPopover();
                    return;
                }

                self.showGroupPreviewPopover($badge, $group, blockType);
            });

            // Search input focus
            this.$wrapper.on('focus', '.entity-search-input', function() {
                var $picker = $(this).closest('.value-picker');
                var $group = $(this).closest('.selection-group');
                var $block = $(this).closest('.target-block');
                var blockType = $block.data('blockType');
                var groupIndex = parseInt($group.data('groupIndex'), 10);
                var section = $picker.hasClass('include-picker') ? 'include' : 'exclude';
                var searchEntity = $picker.attr('data-search-entity') || blockType;

                var excludeIndex = null;
                if (section === 'exclude') {
                    var $excludeRow = $(this).closest('.exclude-row');
                    if ($excludeRow.length) {
                        excludeIndex = parseInt($excludeRow.data('excludeIndex'), 10);
                    }
                }

                var entityChanged = self.activeGroup && self.activeGroup.searchEntity !== searchEntity;
                if (entityChanged) {
                    self.searchResults = [];
                    self.searchOffset = 0;
                    self.searchQuery = '';
                    self.viewMode = 'list';
                    self.resetFiltersWithoutSearch();
                    self.$dropdown.find('.dropdown-results').empty();
                    self.$dropdown.find('.filter-panel').removeClass('show');
                    self.$dropdown.find('.btn-toggle-filters').removeClass('active');
                }

                self.activeGroup = {
                    blockType: blockType,
                    groupIndex: groupIndex,
                    section: section,
                    excludeIndex: excludeIndex,
                    searchEntity: searchEntity
                };

                // Initialize pending selections from current chips
                var $chips = $picker.find('.entity-chips');
                self.pendingSelections = [];
                $chips.find('.entity-chip').each(function() {
                    self.pendingSelections.push({
                        id: $(this).data('id'),
                        name: $(this).find('.chip-name').text(),
                        data: $(this).data()
                    });
                });
                self.pendingPicker = $picker;
                self.pendingRow = section === 'include' ? $group.find('.group-include') : $group.find('.exclude-row[data-exclude-index="' + excludeIndex + '"]');

                self.searchOffset = 0;
                self.searchQuery = $(this).val().trim();

                self.updateFilterPanelForEntity(searchEntity);

                if (searchEntity === 'products') {
                    self.loadFilterableData();
                }

                self.positionDropdown($(this));

                // For tree view mode on categories, load category tree instead of search
                if (self.viewMode === 'tree' && (searchEntity === 'categories' || searchEntity === 'cms_categories')) {
                    self.loadCategoryTree();
                    return;
                }

                self.performSearch();
            });

            // Search input typing
            this.$wrapper.on('input', '.entity-search-input', function() {
                var query = $(this).val().trim();
                self.searchQuery = query;
                self.searchOffset = 0;

                if (self.viewMode === 'tree') {
                    self.filterCategoryTree(query);
                    return;
                }

                clearTimeout(self.searchTimeout);
                self.searchTimeout = setTimeout(function() {
                    self.performSearch();
                }, 300);
            });

            // History item click
            this.$dropdown.on('click', '.history-item', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var query = $(this).data('query');
                if (query && self.activeGroup) {
                    var $input = self.$wrapper.find('.entity-search-input:focus');
                    if (!$input.length) {
                        var $block = self.$wrapper.find('.target-block[data-block-type="' + self.activeGroup.blockType + '"]');
                        var $group = $block.find('.selection-group[data-group-index="' + self.activeGroup.groupIndex + '"]');
                        $input = $group.find('.entity-search-input').first();
                    }
                    $input.val(query);
                    self.searchQuery = query;
                    self.searchOffset = 0;
                    self.performSearch();
                }
            });

            // Delete history item
            this.$dropdown.on('click', '.history-item .btn-delete-history', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $item = $(this).closest('.history-item');
                var query = $item.data('query');
                if (query && self.activeGroup) {
                    self.removeFromSearchHistory(self.activeGroup.searchEntity, query);
                    $item.fadeOut(150, function() {
                        $(this).remove();
                        if (!self.$dropdown.find('.history-item').length) {
                            self.performSearch();
                        }
                    });
                }
            });

            // Dropdown item click
            this.$dropdown.on('click', '.dropdown-item', function(e) {
                e.preventDefault();

                // Blur any focused input so Ctrl+A works for select all
                $(document.activeElement).filter('input, textarea').blur();

                var $item = $(this);
                var id = $item.data('id');
                var name = $item.data('name');
                var isSelected = $item.hasClass('selected');

                if (!self.activeGroup) return;

                var $block = self.$wrapper.find('.target-block[data-block-type="' + self.activeGroup.blockType + '"]');
                var $group = $block.find('.selection-group[data-group-index="' + self.activeGroup.groupIndex + '"]');
                var $picker;
                var $row;

                if (self.activeGroup.section === 'include') {
                    $picker = $group.find('.include-picker');
                    $row = $group.find('.group-include');
                } else {
                    var $excludeRow = $group.find('.exclude-row[data-exclude-index="' + self.activeGroup.excludeIndex + '"]');
                    $picker = $excludeRow.find('.exclude-picker');
                    $row = $excludeRow;
                }

                // Ensure pendingSelections is initialized
                if (!self.pendingSelections) self.pendingSelections = [];

                if (isSelected) {
                    // Remove from pending selections
                    self.pendingSelections = self.pendingSelections.filter(function(s) {
                        return parseInt(s.id, 10) !== parseInt(id, 10);
                    });
                    self.removeSelection($picker, id);
                    $item.toggleClass('selected');
                    self.serializeAllBlocks($row);
                } else {
                    // Validate selection before adding
                    var section = self.activeGroup.section;
                    var validation = self.validateSelection(id, name, section, $item.data());
                    if (!validation.valid) {
                        self.showValidationError(validation.error);
                        return;
                    }

                    var activeBlockType = self.activeGroup.blockType;
                    var currentSelection = self.getCurrentSingleSelection(activeBlockType);
                    if (currentSelection) {
                        var newEntityType = activeBlockType;
                        self.showReplaceConfirmation(currentSelection, { name: name, entityType: newEntityType }, function() {
                            // Add to pending selections
                            self.pendingSelections.push({ id: id, name: name, data: $item.data() });
                            self.addSelection($picker, id, name, $item.data());
                            $item.addClass('selected');
                            self.serializeAllBlocks($row);
                        });
                    } else {
                        // Add to pending selections
                        var exists = self.pendingSelections.some(function(s) {
                            return parseInt(s.id, 10) === parseInt(id, 10);
                        });
                        if (!exists) {
                            self.pendingSelections.push({ id: id, name: name, data: $item.data() });
                        }
                        self.addSelection($picker, id, name, $item.data());
                        $item.toggleClass('selected');
                        self.serializeAllBlocks($row);
                    }
                }
            });

            // Chip remove
            this.$wrapper.on('click', '.chip-remove', function(e) {
                e.stopPropagation();
                var $chip = $(this).closest('.entity-chip');
                var $picker = $(this).closest('.value-picker');
                var $row = $(this).closest('.group-include, .exclude-row');
                var id = $chip.data('id');

                console.log('[EntitySelector] Chip remove clicked, id:', id);

                // Also remove from pending selections if dropdown is open
                if (self.pendingSelections) {
                    self.pendingSelections = self.pendingSelections.filter(function(s) {
                        return parseInt(s.id, 10) !== parseInt(id, 10);
                    });
                }

                self.removeSelection($picker, id);
                console.log('[EntitySelector] Calling serializeAllBlocks after chip remove');
                self.serializeAllBlocks($row);

                if (self.$dropdown && self.$dropdown.hasClass('show')) {
                    self.$dropdown.find('.dropdown-item[data-id="' + id + '"]').removeClass('selected');
                }
            });

            // Country chip holiday preview
            this.$wrapper.on('click', '.chip-preview-holidays', function(e) {
                e.stopPropagation();
                e.preventDefault();

                var $btn = $(this);
                var $chip = $btn.closest('.entity-chip');
                var countryId = $chip.data('id');
                var countryName = $chip.find('.chip-name').text();
                var countryIso = $chip.data('iso') || '';

                self.showHolidayPreview(countryId, countryName, countryIso, $btn);
            });

            // Chips show more/less toggle
            this.$wrapper.on('click', '.chips-show-more-toggle', function(e) {
                e.stopPropagation();
                var $chips = $(this).closest('.entity-chips');

                if ($chips.hasClass('chips-expanded')) {
                    $chips.removeClass('chips-expanded').addClass('chips-collapsed');
                } else {
                    $chips.addClass('chips-expanded').removeClass('chips-collapsed');
                }

                self.updateChipsVisibility($chips);
            });

            // Select All
            this.$dropdown.on('click', '.btn-select-all', function(e) {
                e.preventDefault();
                if (!self.activeGroup) return;

                var section = self.activeGroup.section;
                var skippedCount = 0;

                // Handle tree view - use pending selections
                if (self.viewMode === 'tree') {
                    if (!self.pendingSelections) self.pendingSelections = [];

                    // Select all visible (not filtered-out) tree items
                    var $visibleTreeItems = self.$dropdown.find('.tree-item:not(.filtered-out)');
                    $visibleTreeItems.each(function() {
                        var $item = $(this);
                        var id = parseInt($item.data('id'), 10);
                        var name = $item.data('name');

                        if (!$item.hasClass('selected')) {
                            // Validate before adding
                            var validation = self.validateSelection(id, name, section, $item.data());
                            if (!validation.valid) {
                                skippedCount++;
                                return; // Skip this item
                            }

                            $item.addClass('selected');
                            var exists = self.pendingSelections.some(function(s) {
                                return parseInt(s.id, 10) === id;
                            });
                            if (!exists) {
                                self.pendingSelections.push({ id: id, name: name, data: $item.data() });
                            }
                        }
                    });

                    // Show warning if items were skipped
                    if (skippedCount > 0) {
                        var trans = self.config.trans || {};
                        var msg = (trans.items_skipped_conflicts || '{count} item(s) were skipped due to conflicts.').replace('{count}', skippedCount);
                        self.showValidationError(msg);
                    }

                    // Update count display
                    var selectedCount = self.$dropdown.find('.tree-item.selected').length;
                    var totalCount = self.$dropdown.find('.tree-item').length;
                    var entityType = self.$dropdown.find('.category-tree').data('entity-type') || 'categories';
                    var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';
                    self.$dropdown.find('.results-count').text(totalCount + ' ' + categoryLabel + ' (' + selectedCount + ' selected)');
                    return;
                }

                // Handle list view
                var $block = self.$wrapper.find('.target-block[data-block-type="' + self.activeGroup.blockType + '"]');
                var $group = $block.find('.selection-group[data-group-index="' + self.activeGroup.groupIndex + '"]');
                var $picker;
                var $row;

                if (self.activeGroup.section === 'include') {
                    $picker = $group.find('.include-picker');
                    $row = $group.find('.group-include');
                } else {
                    var $excludeRow = $group.find('.exclude-row[data-exclude-index="' + self.activeGroup.excludeIndex + '"]');
                    $picker = $excludeRow.find('.exclude-picker');
                    $row = $excludeRow;
                }

                // Ensure pendingSelections is initialized
                if (!self.pendingSelections) self.pendingSelections = [];

                var $visibleItems = self.$dropdown.find('.dropdown-item:visible');
                $visibleItems.each(function() {
                    if (!$(this).hasClass('selected')) {
                        var id = $(this).data('id');
                        var name = $(this).data('name');

                        // Validate before adding
                        var validation = self.validateSelection(id, name, section, $(this).data());
                        if (!validation.valid) {
                            skippedCount++;
                            return; // Skip this item
                        }

                        // Add to pending selections for Save button
                        var exists = self.pendingSelections.some(function(s) {
                            return parseInt(s.id, 10) === parseInt(id, 10);
                        });
                        if (!exists) {
                            self.pendingSelections.push({
                                id: id,
                                name: name,
                                data: $(this).data()
                            });
                        }

                        self.addSelectionNoUpdate($picker, id, name, $(this).data());
                        $(this).addClass('selected');
                    }
                });

                // Show warning if items were skipped
                if (skippedCount > 0) {
                    var trans = self.config.trans || {};
                    var msg = (trans.items_skipped_conflicts || '{count} item(s) were skipped due to conflicts.').replace('{count}', skippedCount);
                    self.showValidationError(msg);
                }

                var $chips = $picker.find('.entity-chips');
                self.updateChipsVisibility($chips);

                self.serializeAllBlocks($row);
            });

            // Clear selection
            this.$dropdown.on('click', '.btn-clear-selection', function(e) {
                e.preventDefault();
                if (!self.activeGroup) return;

                // Handle tree view - clear pending selections
                if (self.viewMode === 'tree') {
                    self.pendingSelections = [];
                    self.$dropdown.find('.tree-item').removeClass('selected');

                    // Update count display
                    var totalCount = self.$dropdown.find('.tree-item').length;
                    var entityType = self.$dropdown.find('.category-tree').data('entity-type') || 'categories';
                    var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';
                    self.$dropdown.find('.results-count').text(totalCount + ' ' + categoryLabel);
                    return;
                }

                // Handle list view
                var $block = self.$wrapper.find('.target-block[data-block-type="' + self.activeGroup.blockType + '"]');
                var $group = $block.find('.selection-group[data-group-index="' + self.activeGroup.groupIndex + '"]');
                var $picker;
                var $row;

                if (self.activeGroup.section === 'include') {
                    $picker = $group.find('.include-picker');
                    $row = $group.find('.group-include');
                } else {
                    var $excludeRow = $group.find('.exclude-row[data-exclude-index="' + self.activeGroup.excludeIndex + '"]');
                    $picker = $excludeRow.find('.exclude-picker');
                    $row = $excludeRow;
                }

                // Clear pending selections for list view too
                self.pendingSelections = [];

                var $chips = $picker.find('.entity-chips');
                $chips.empty().removeClass('chips-expanded chips-collapsed');
                self.$dropdown.find('.dropdown-item').removeClass('selected');
                self.serializeAllBlocks($row);
            });

            // Save - commit pending selections to chips
            this.$dropdown.on('click', '.btn-save', function(e) {
                e.preventDefault();

                if (self.pendingPicker && self.pendingSelections) {
                    var $chips = self.pendingPicker.find('.entity-chips');

                    // Clear existing chips
                    $chips.empty();

                    // Add chips for all pending selections
                    self.pendingSelections.forEach(function(sel) {
                        self.addSelectionNoUpdate(self.pendingPicker, sel.id, sel.name, sel.data);
                    });

                    self.updateChipsVisibility($chips);

                    // Serialize to hidden input
                    if (self.pendingRow) {
                        self.serializeAllBlocks(self.pendingRow);
                    }
                }

                self.pendingSelections = null;
                self.pendingPicker = null;
                self.pendingRow = null;
                self.hideDropdown();
            });

            // Cancel - discard pending selections (no changes to chips)
            this.$dropdown.on('click', '.btn-cancel', function(e) {
                e.preventDefault();

                // Just discard pending - chips remain unchanged
                self.pendingSelections = null;
                self.pendingPicker = null;
                self.pendingRow = null;
                self.hideDropdown();
            });

            // Load more
            this.$dropdown.on('click', '.btn-load-more', function(e) {
                e.preventDefault();
                if (self.isLoading) return;

                var loadCount = parseInt(self.$dropdown.find('.load-more-select').val(), 10) || 20;
                self.searchOffset = self.searchResults.length;
                self.loadMoreCount = loadCount;
                self.performSearch(true);
            });

            // Sort field change
            this.$dropdown.on('change', '.sort-field-select', function() {
                self.currentSort.field = $(this).val();
                self.refreshSearch();
            });

            // Sort direction toggle
            this.$dropdown.on('click', '.btn-sort-dir', function(e) {
                e.preventDefault();
                var $btn = $(this);
                var currentDir = $btn.data('dir');
                var newDir = currentDir === 'ASC' ? 'DESC' : 'ASC';
                $btn.data('dir', newDir);
                $btn.find('i').replaceWith(this.esIcon('sort_by_alpha'));
                self.currentSort.dir = newDir;
                self.refreshSearch();
            });

            // Tree view: Toggle expand/collapse
            this.$dropdown.on('click', '.category-tree .tree-toggle', function(e) {
                e.stopPropagation();
                var $item = $(this).closest('.tree-item');
                var $allItems = self.$dropdown.find('.tree-item');

                $item.toggleClass('collapsed');
                var isCollapsed = $item.hasClass('collapsed');

                $(this).find('i').text(isCollapsed ? 'arrow_right' : 'arrow_drop_down');

                var descendants = self.findTreeDescendants($item, $allItems);
                for (var i = 0; i < descendants.length; i++) {
                    $(descendants[i]).toggle(!isCollapsed);
                }
            });

            // Tree view: Item click (select/deselect) - PENDING mode
            this.$dropdown.on('click', '.category-tree .tree-item', function(e) {
                if ($(e.target).closest('.tree-toggle, .btn-select-children, .tree-count').length) {
                    return;
                }

                // Blur any focused input so Ctrl+A works for select all
                $(document.activeElement).filter('input, textarea').blur();

                var $item = $(this);
                var id = parseInt($item.data('id'), 10);
                var name = $item.data('name');
                var isSelected = $item.hasClass('selected');

                if (!self.activeGroup) {
                    return;
                }
                if (!self.pendingSelections) self.pendingSelections = [];

                var $allItems = self.$dropdown.find('.tree-item');

                var updateCount = function() {
                    var selectedCount = self.$dropdown.find('.tree-item.selected').length;
                    var totalCount = self.$dropdown.find('.tree-item').length;
                    var entityType = self.$dropdown.find('.category-tree').data('entity-type') || 'categories';
                    var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';
                    self.$dropdown.find('.results-count').text(totalCount + ' ' + categoryLabel + (selectedCount > 0 ? ' (' + selectedCount + ' selected)' : ''));
                    self.updateSelectChildrenButtons($allItems);
                };

                if (isSelected) {
                    // Remove from pending
                    self.pendingSelections = self.pendingSelections.filter(function(s) {
                        return parseInt(s.id, 10) !== id;
                    });
                    $item.removeClass('selected');
                } else {
                    // Validate selection before adding to pending
                    var section = self.activeGroup.section;
                    var validation = self.validateSelection(id, name, section, $item.data());
                    if (!validation.valid) {
                        self.showValidationError(validation.error);
                        return;
                    }

                    // Add to pending
                    var exists = self.pendingSelections.some(function(s) {
                        return parseInt(s.id, 10) === id;
                    });
                    if (!exists) {
                        self.pendingSelections.push({
                            id: id,
                            name: name,
                            data: $item.data()
                        });
                    }
                    $item.addClass('selected');
                }

                updateCount();
            });

            // Tree view: Product/page count click - show preview
            this.$dropdown.on('click', '.category-tree .tree-count.clickable', function(e) {
                e.preventDefault();
                e.stopPropagation();
                var $count = $(this);
                var categoryId = $count.data('category-id');
                var $item = $count.closest('.tree-item');
                var categoryName = $item.data('name');
                var entityType = self.$dropdown.find('.category-tree').data('entity-type') || 'categories';

                if ($count.hasClass('popover-open')) {
                    self.hidePreviewPopover();
                } else {
                    self.showCategoryItemsPreview($count, categoryId, categoryName, entityType);
                }
            });

            // Tree view: Select/Deselect with children button (toggle)
            this.$dropdown.on('click', '.category-tree .btn-select-children', function(e) {
                e.stopPropagation();
                var $btn = $(this);
                var $item = $btn.closest('.tree-item');
                var $allItems = self.$dropdown.find('.tree-item');

                if (!self.activeGroup) return;

                var $block = self.$wrapper.find('.target-block[data-block-type="' + self.activeGroup.blockType + '"]');
                var $group = $block.find('.selection-group[data-group-index="' + self.activeGroup.groupIndex + '"]');
                var $picker;
                var $row;

                if (self.activeGroup.section === 'include') {
                    $picker = $group.find('.include-picker');
                    $row = $group.find('.group-include');
                } else {
                    var $excludeRow = $group.find('.exclude-row[data-exclude-index="' + self.activeGroup.excludeIndex + '"]');
                    $picker = $excludeRow.find('.exclude-picker');
                    $row = $excludeRow;
                }

                var descendants = self.findTreeDescendants($item, $allItems);

                var allSelected = $item.hasClass('selected');
                for (var i = 0; i < descendants.length && allSelected; i++) {
                    if (!$(descendants[i]).hasClass('selected')) {
                        allSelected = false;
                    }
                }

                var trans = self.config.trans || {};

                if (allSelected) {
                    self.removeSelection($picker, $item.data('id'));
                    $item.removeClass('selected');

                    for (var j = 0; j < descendants.length; j++) {
                        var $child = $(descendants[j]);
                        self.removeSelection($picker, $child.data('id'));
                        $child.removeClass('selected');
                    }

                    $btn.find('i').replaceWith(self.esIcon('add_box'));
                    $btn.attr('title', trans.select_with_children || 'Select with all children');
                } else {
                    var section = self.activeGroup.section;
                    var skippedChildren = 0;

                    if (!$item.hasClass('selected')) {
                        // Validate parent first
                        var parentValidation = self.validateSelection($item.data('id'), $item.data('name'), section, $item.data());
                        if (parentValidation.valid) {
                            self.addSelectionNoUpdate($picker, $item.data('id'), $item.data('name'), $item.data());
                            $item.addClass('selected');
                        } else {
                            self.showValidationError(parentValidation.error);
                            return; // Can't select parent, abort entire operation
                        }
                    }

                    for (var k = 0; k < descendants.length; k++) {
                        var $descendant = $(descendants[k]);
                        if (!$descendant.hasClass('selected')) {
                            // Validate each child
                            var childValidation = self.validateSelection($descendant.data('id'), $descendant.data('name'), section, $descendant.data());
                            if (childValidation.valid) {
                                self.addSelectionNoUpdate($picker, $descendant.data('id'), $descendant.data('name'), $descendant.data());
                                $descendant.addClass('selected');
                            } else {
                                skippedChildren++;
                            }
                        }
                    }

                    // Show warning if children were skipped
                    if (skippedChildren > 0) {
                        var skipMsg = (trans.children_skipped_conflicts || '{count} child item(s) were skipped due to conflicts.').replace('{count}', skippedChildren);
                        self.showValidationError(skipMsg);
                    }

                    $btn.find('i').replaceWith(self.esIcon('indeterminate_check_box'));
                    $btn.attr('title', trans.deselect_with_children || 'Deselect with all children');
                }

                var $chips = $picker.find('.entity-chips');
                self.updateChipsVisibility($chips);

                self.serializeAllBlocks($row);
                self.updateSelectChildrenButtons($allItems);

                var selectedCount = self.$dropdown.find('.tree-item.selected').length;
                var totalCount = self.$dropdown.find('.tree-item').length;
                var entityType = self.$dropdown.find('.category-tree').data('entity-type') || 'categories';
                var categoryLabel = entityType === 'cms_categories' ? 'CMS categories' : 'categories';
                self.$dropdown.find('.results-count').text(totalCount + ' ' + categoryLabel + (selectedCount > 0 ? ' (' + selectedCount + ' selected)' : ''));
            });

            // Tree view: Expand all
            this.$dropdown.on('click', '.category-tree .btn-expand-all', function(e) {
                e.preventDefault();
                self.$dropdown.find('.tree-item').removeClass('collapsed').show();
                self.$dropdown.find('.tree-toggle i').replaceWith(this.esIcon('arrow_drop_down'));
            });

            // Tree view: Collapse all
            this.$dropdown.on('click', '.category-tree .btn-collapse-all', function(e) {
                e.preventDefault();
                var minLevel = Infinity;
                self.$dropdown.find('.tree-item').each(function() {
                    var level = parseInt($(this).data('level'), 10);
                    if (level < minLevel) minLevel = level;
                });

                self.$dropdown.find('.tree-item').each(function() {
                    var $item = $(this);
                    var level = parseInt($item.data('level'), 10);
                    var hasChildren = $item.hasClass('has-children');

                    if (level === minLevel) {
                        if (hasChildren) {
                            $item.addClass('collapsed');
                            $item.find('.tree-toggle i').replaceWith(self.esIcon('arrow_right'));
                        }
                        $item.show();
                    } else {
                        $item.hide();
                    }
                });
            });

            // Refine search input
            this.$dropdown.on('keyup', '.refine-input', function() {
                var query = $(this).val().trim();
                self.refineQuery = query;
                self.$dropdown.find('.btn-clear-refine').toggle(query.length > 0);

                clearTimeout(self.refineTimeout);
                self.refineTimeout = setTimeout(function() {
                    // For tree view, filter client-side instead of server refresh
                    if (self.viewMode === 'tree') {
                        self.filterCategoryTree(query);
                        return;
                    }
                    self.refreshSearch();
                }, 300);
            });

            // Clear refine search
            this.$dropdown.on('click', '.btn-clear-refine', function(e) {
                e.preventDefault();
                self.refineQuery = '';
                self.$dropdown.find('.refine-input').val('');
                $(this).hide();
                // For tree view, filter client-side instead of server refresh
                if (self.viewMode === 'tree') {
                    self.filterCategoryTree('');
                    return;
                }
                self.refreshSearch();
            });

            // Toggle refine negate (NOT contains)
            this.$dropdown.on('click', '.btn-refine-negate', function(e) {
                e.preventDefault();
                self.refineNegate = !self.refineNegate;
                $(this).toggleClass('active', self.refineNegate);

                var trans = self.config.trans || {};
                var placeholder = self.refineNegate
                    ? (trans.refine_exclude || 'Exclude...')
                    : (trans.refine_short || 'Refine...');
                self.$dropdown.find('.refine-input').attr('placeholder', placeholder);

                if (self.refineQuery) {
                    self.refreshSearch();
                }
            });

            // Toggle filter panel
            this.$dropdown.on('click', '.btn-toggle-filters', function(e) {
                e.preventDefault();
                var $panel = self.$dropdown.find('.filter-panel');
                $panel.toggleClass('show');
                $(this).toggleClass('active', $panel.hasClass('show'));

                if ($panel.hasClass('show') && self.activeGroup) {
                    self.updateFilterPanelForEntity(self.activeGroup.searchEntity);
                }
            });

            // Show search history
            this.$dropdown.on('click', '.btn-show-history', function(e) {
                e.preventDefault();
                $(this).toggleClass('active');
                if ($(this).hasClass('active') && self.activeGroup) {
                    self.showSearchHistory(self.activeGroup.searchEntity);
                } else {
                    self.performSearch();
                }
            });

            // Quick filter checkboxes
            this.$dropdown.on('change', '.filter-in-stock', function() {
                self.filters.inStock = $(this).is(':checked');
                self.refreshSearch();
            });

            this.$dropdown.on('change', '.filter-discounted', function() {
                self.filters.discounted = $(this).is(':checked');
                self.refreshSearch();
            });

            // Price range filter
            this.$dropdown.on('change', '.filter-price-min, .filter-price-max', function() {
                var $panel = self.$dropdown.find('.filter-panel');
                self.filters.priceMin = $panel.find('.filter-price-min').val() || null;
                self.filters.priceMax = $panel.find('.filter-price-max').val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Product count range
            this.$dropdown.on('change', '.filter-product-count-min, .filter-product-count-max', function() {
                var $row = $(this).closest('.filter-row');
                self.filters.productCountMin = $row.find('.filter-product-count-min').val() || null;
                self.filters.productCountMax = $row.find('.filter-product-count-max').val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Sales range
            this.$dropdown.on('change', '.filter-sales-min, .filter-sales-max', function() {
                var $row = $(this).closest('.filter-row');
                self.filters.salesMin = $row.find('.filter-sales-min').val() || null;
                self.filters.salesMax = $row.find('.filter-sales-max').val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Turnover/revenue range
            this.$dropdown.on('change', '.filter-turnover-min, .filter-turnover-max', function() {
                var $row = $(this).closest('.filter-row');
                self.filters.turnoverMin = $row.find('.filter-turnover-min').val() || null;
                self.filters.turnoverMax = $row.find('.filter-turnover-max').val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Date added range
            this.$dropdown.on('change', '.filter-date-add-from, .filter-date-add-to', function() {
                var $row = $(this).closest('.filter-row');
                self.filters.dateAddFrom = $row.find('.filter-date-add-from').val() || null;
                self.filters.dateAddTo = $row.find('.filter-date-add-to').val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Last product date range
            this.$dropdown.on('change', '.filter-last-product-from, .filter-last-product-to', function() {
                var $row = $(this).closest('.filter-row');
                self.filters.lastProductFrom = $row.find('.filter-last-product-from').val() || null;
                self.filters.lastProductTo = $row.find('.filter-last-product-to').val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Depth (categories)
            this.$dropdown.on('change', '.filter-depth-select', function() {
                self.filters.depth = $(this).val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Has products (categories)
            this.$dropdown.on('change', '.filter-has-products', function() {
                self.filters.hasProducts = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: Has description (categories)
            this.$dropdown.on('change', '.filter-has-description', function() {
                self.filters.hasDescription = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: Has image (categories)
            this.$dropdown.on('change', '.filter-has-image', function() {
                self.filters.hasImage = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: Active only
            this.$dropdown.on('change', '.filter-active-only', function() {
                self.filters.activeOnly = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: Attribute group select
            this.$dropdown.on('change', '.filter-attribute-group-select', function() {
                self.filters.attributeGroup = $(this).val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Feature group select
            this.$dropdown.on('change', '.filter-feature-group-select', function() {
                self.filters.featureGroup = $(this).val() || null;
                self.refreshSearch();
            });

            // Entity-specific filters: Color attributes only
            this.$dropdown.on('change', '.filter-is-color', function() {
                self.filters.isColor = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: Custom feature values only
            this.$dropdown.on('change', '.filter-is-custom', function() {
                self.filters.isCustom = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: CMS indexable
            this.$dropdown.on('change', '.filter-indexable', function() {
                self.filters.indexable = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: Countries - Has holidays
            this.$dropdown.on('change', '.filter-has-holidays', function() {
                self.filters.hasHolidays = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: Countries - Contains states
            this.$dropdown.on('change', '.filter-contains-states', function() {
                self.filters.containsStates = $(this).is(':checked');
                self.refreshSearch();
            });

            // Entity-specific filters: Countries - Zone select
            this.$dropdown.on('change', '.filter-zone-select', function() {
                self.filters.zone = $(this).val() || null;
                self.refreshSearch();
            });

            // Clear entity-specific filters
            this.$dropdown.on('click', '.filter-row-entity-categories .btn-clear-filters, .filter-row-entity-manufacturers .btn-clear-filters, .filter-row-entity-suppliers .btn-clear-filters, .filter-row-entity-attributes .btn-clear-filters, .filter-row-entity-features .btn-clear-filters, .filter-row-entity-cms .btn-clear-filters, .filter-row-entity-cms-categories .btn-clear-filters, .filter-row-entity-countries .btn-clear-filters', function(e) {
                e.preventDefault();
                var $row = $(this).closest('.filter-row');
                $row.find('input[type="number"]').val('');
                $row.find('input[type="date"]').val('');
                $row.find('select').val('');
                $row.find('input[type="checkbox"]').prop('checked', false);
                $row.find('.filter-active-only').prop('checked', true);

                self.filters.productCountMin = null;
                self.filters.productCountMax = null;
                self.filters.salesMin = null;
                self.filters.salesMax = null;
                self.filters.turnoverMin = null;
                self.filters.turnoverMax = null;
                self.filters.depth = null;
                self.filters.hasProducts = false;
                self.filters.hasDescription = false;
                self.filters.hasImage = false;
                self.filters.activeOnly = true;
                self.filters.attributeGroup = null;
                self.filters.featureGroup = null;
                self.filters.isColor = false;
                self.filters.isCustom = false;
                self.filters.indexable = false;
                self.filters.dateAddFrom = null;
                self.filters.dateAddTo = null;
                self.filters.lastProductFrom = null;
                self.filters.lastProductTo = null;
                // Country filters
                self.filters.hasHolidays = false;
                self.filters.containsStates = false;
                self.filters.zone = null;
                self.refreshSearch();
            });

            // Toggle filter group - show values
            this.$dropdown.on('click', '.filter-group-toggle', function(e) {
                // Ignore clicks on the preview badge
                if ($(e.target).closest('.toggle-count.clickable').length) {
                    return;
                }
                e.preventDefault();
                var $btn = $(this);
                var groupId = $btn.data('group-id');
                var type = $btn.data('type');
                var isActive = $btn.hasClass('active');

                self.$dropdown.find('.filter-group-toggle').removeClass('active');

                if (isActive) {
                    self.hideFilterGroupValues();
                } else {
                    $btn.addClass('active');
                    self.showFilterGroupValues(groupId, type);
                }
            });

            // Filter group toggle count badge click for preview popover
            this.$dropdown.on('click', '.filter-group-toggle .toggle-count.clickable', function(e) {
                e.stopPropagation();
                e.preventDefault();

                var $badge = $(this);
                var groupId = $badge.data('groupId');
                var groupType = $badge.data('type');
                var groupName = $badge.data('groupName');

                if ($badge.hasClass('popover-open')) {
                    self.hidePreviewPopover();
                } else {
                    self.showFilterGroupPreviewPopover($badge, groupId, groupType, groupName);
                }
            });

            // View mode select change
            this.$dropdown.on('change', '.view-mode-select', function() {
                var mode = $(this).val();
                var prevMode = self.viewMode;
                self.viewMode = mode;

                // Remove all view mode classes and add the new one
                self.$dropdown
                    .removeClass('view-list view-tree view-cols-2 view-cols-3 view-cols-4 view-cols-5 view-cols-6 view-cols-7 view-cols-8')
                    .addClass('view-' + mode.replace('cols-', 'cols-'));

                // For tree view, load the category tree (only for categories/cms_categories)
                var searchEntity = self.activeGroup ? self.activeGroup.searchEntity : '';
                if (mode === 'tree' && (searchEntity === 'categories' || searchEntity === 'cms_categories')) {
                    self.loadCategoryTree();
                } else if (mode !== 'tree') {
                    // If switching FROM tree mode, need to refresh search to load data
                    if (prevMode === 'tree') {
                        self.refreshSearch();
                    } else {
                        // Re-render current results with new view mode
                        self.renderSearchResults(false);
                    }
                }
            });

            // Close values row
            this.$dropdown.on('click', '.btn-close-values', function(e) {
                e.preventDefault();
                e.stopPropagation();
                self.hideFilterGroupValues();
            });

            // Toggle filter chip (attribute/feature value)
            this.$dropdown.on('click', '.filter-chip', function(e) {
                e.preventDefault();
                e.stopPropagation();

                var $chip = $(this);
                var id = parseInt($chip.data('id'), 10);
                var isAttribute = $chip.hasClass('filter-attr-chip');
                var filterArray = isAttribute ? self.filters.attributes : self.filters.features;

                var index = filterArray.indexOf(id);
                if (index === -1) {
                    filterArray.push(id);
                    $chip.addClass('active');
                } else {
                    filterArray.splice(index, 1);
                    $chip.removeClass('active');
                }

                self.updateFilterToggleStates();
                self.refreshSearch();
            });

            // Clear all filters
            this.$dropdown.on('click', '.filter-row-quick .btn-clear-filters', function(e) {
                e.preventDefault();
                self.clearFilters();
            });

            // Click outside to close
            $(document).on('click', function(e) {
                if (!$(e.target).closest('.value-picker').length &&
                    !$(e.target).closest('.target-search-dropdown').length &&
                    !$(e.target).closest('.target-preview-popover').length) {
                    self.hideDropdown();
                }
            });

            // Keyboard shortcuts
            $(document).on('keydown', function(e) {
                if (!self.$dropdown || !self.$dropdown.hasClass('show')) return;

                // Allow default behavior in input/textarea fields
                var isInputFocused = $(document.activeElement).is('input, textarea');

                // Ctrl+A / Cmd+A - Select All (only when not in input)
                if ((e.ctrlKey || e.metaKey) && e.keyCode === 65) {
                    if (isInputFocused) return; // Let browser select text
                    e.preventDefault();
                    e.stopPropagation();
                    self.$dropdown.find('.btn-select-all').trigger('click');
                    return false;
                }

                // Ctrl+D / Cmd+D - Clear/Deselect all (only when not in input)
                if ((e.ctrlKey || e.metaKey) && e.keyCode === 68) {
                    if (isInputFocused) return; // Let browser handle
                    e.preventDefault();
                    e.stopPropagation();
                    self.$dropdown.find('.btn-clear-selection').trigger('click');
                    return false;
                }

                if (e.key === 'Escape') {
                    e.preventDefault();
                    self.hideDropdown();
                } else if (e.key === 'Enter') {
                    e.preventDefault();
                    self.hideDropdown();
                }
            });

        }
    };

})(jQuery);
