/* ============================================
   RSL Select Component
   Version: 2.0.0
   Description: Fully accessible custom select with single/multi-select,
                search/filter, keyboard navigation, and ARIA compliance

   FilterBus Integration (v2.0.0):
   - Bidirectional: Can publish selection changes AND subscribe to filter state
   - data-filterbus-publish="key" - Publish selection to FilterBus with this key
   - data-filterbus-subscribe="key" - Subscribe to FilterBus and update selection
   - data-filter-value="value" - For visibility filtering (show/hide based on match)
   ============================================ */

(function() {
    'use strict';

    // Initialize RSL namespace
    window.RSL = window.RSL || {};

    /**
     * Select Component
     * Creates accessible custom select dropdowns with extensive features
     */
    window.RSL.Select = {

        /**
         * All active select instances
         * @type {Map}
         */
        instances: new Map(),

        /**
         * Track FilterBus subscriptions for cleanup
         * @type {Map<HTMLElement, string>}
         */
        filterSubscriptions: new Map(),

        /**
         * Initialize all selects on the page
         */
        init: function() {
            var selects = document.querySelectorAll('[data-rsl-select]');
            selects.forEach(function(element) {
                if (!RSL.Select.instances.has(element)) {
                    RSL.Select.create(element);
                }
            });
        },

        /**
         * Create a new select instance
         * @param {HTMLElement} element - The element to transform into a select
         * @returns {Object} Select instance
         */
        create: function(element) {
            var instance = {
                element: element,
                config: RSL.Select.getConfig(element),
                selectedValues: [],
                filteredOptions: [],
                focusedIndex: -1,
                isOpen: false,
                _skipPublish: false  // Flag to prevent publish loops
            };

            // Build the select UI
            RSL.Select.build(instance);

            // Store instance
            RSL.Select.instances.set(element, instance);

            // Setup FilterBus integration (if configured)
            RSL.Select.setupFilterBus(instance);

            return instance;
        },

        /**
         * Get configuration from data attributes
         * @param {HTMLElement} element
         * @returns {Object} Configuration object
         */
        getConfig: function(element) {
            return {
                // Basic settings
                placeholder: element.getAttribute('data-rsl-select-placeholder') || 'Select an option...',
                multiSelect: element.getAttribute('data-rsl-select-multi') === 'true',
                searchable: element.getAttribute('data-rsl-select-searchable') === 'true',
                clearable: element.getAttribute('data-rsl-select-clearable') === 'true',
                disabled: element.getAttribute('data-rsl-select-disabled') === 'true',
                required: element.hasAttribute('data-required') || element.hasAttribute('required'),

                // Appearance
                size: element.getAttribute('data-rsl-select-size') || 'md', // sm, md, lg
                maxHeight: element.getAttribute('data-rsl-select-max-height') || '300px',
                position: element.getAttribute('data-rsl-select-position') || 'auto', // auto, above, below

                // Multi-select settings
                showCount: element.getAttribute('data-rsl-select-show-count') !== 'false',
                showChips: element.getAttribute('data-rsl-select-show-chips') === 'true',
                chipsToggleable: element.getAttribute('data-rsl-select-chips-toggle') !== 'false',
                maxSelections: parseInt(element.getAttribute('data-rsl-select-max-selections')) || Infinity,

                // Search settings
                searchPlaceholder: element.getAttribute('data-rsl-select-search-placeholder') || 'Search...',
                noResultsText: element.getAttribute('data-rsl-select-no-results') || 'No results found',

                // Form integration
                name: element.getAttribute('data-rsl-select-name') || element.getAttribute('name') || '',
                createHiddenSelect: element.getAttribute('data-rsl-select-hidden') !== 'false',

                // Callbacks
                onChange: element.getAttribute('data-rsl-select-onchange') || null,
                onOpen: element.getAttribute('data-rsl-select-onopen') || null,
                onClose: element.getAttribute('data-rsl-select-onclose') || null,

                // FilterBus integration (bidirectional)
                filterBusPublish: element.getAttribute('data-filterbus-publish') || null,
                filterBusSubscribe: element.getAttribute('data-filterbus-subscribe') || null,
                filterValue: element.getAttribute('data-filter-value') || null
            };
        },

        /**
         * Build the select UI
         * @param {Object} instance
         */
        build: function(instance) {
            var element = instance.element;
            var config = instance.config;

            // Get options from data attribute or child elements
            var optionsData = RSL.Select.getOptionsData(element);
            instance.allOptions = optionsData;
            instance.filteredOptions = optionsData.slice();

            // Create wrapper
            var wrapper = document.createElement('div');
            wrapper.className = 'rsl-select';
            if (config.size !== 'md') {
                wrapper.classList.add('rsl-select-' + config.size);
            }
            if (config.multiSelect) {
                wrapper.classList.add('multi-select');
            }
            if (config.disabled) {
                wrapper.classList.add('disabled');
            }

            // Create trigger button
            var trigger = RSL.Select.createTrigger(instance);
            wrapper.appendChild(trigger);
            instance.trigger = trigger;

            // Create chips container (for multi-select)
            if (config.multiSelect) {
                var chipsContainer = RSL.Select.createChipsContainer(instance);
                wrapper.appendChild(chipsContainer);
                instance.chipsContainer = chipsContainer;

                // Create chips toggle button
                if (config.chipsToggleable) {
                    var chipsToggle = RSL.Select.createChipsToggle(instance);
                    wrapper.appendChild(chipsToggle);
                    instance.chipsToggle = chipsToggle;
                }
            }

            // Create dropdown
            var dropdown = RSL.Select.createDropdown(instance);
            wrapper.appendChild(dropdown);
            instance.dropdown = dropdown;

            // Create hidden select for form submission
            if (config.createHiddenSelect && config.name) {
                var hiddenSelect = RSL.Select.createHiddenSelect(instance);
                wrapper.appendChild(hiddenSelect);
                instance.hiddenSelect = hiddenSelect;
            }

            // Replace original element with wrapper
            element.parentNode.insertBefore(wrapper, element);
            element.style.display = 'none';
            instance.wrapper = wrapper;

            // Attach event listeners
            RSL.Select.attachEvents(instance);
        },

        /**
         * Get options data from element
         * @param {HTMLElement} element
         * @returns {Array} Options data
         */
        getOptionsData: function(element) {
            // Try to get from data-rsl-select-options JSON
            var optionsAttr = element.getAttribute('data-rsl-select-options');
            if (optionsAttr) {
                try {
                    return JSON.parse(optionsAttr);
                } catch (e) {
                    console.error('RSL Select: Invalid JSON in data-rsl-select-options', e);
                }
            }

            // Otherwise, get from child option elements
            var options = [];
            var optionElements = element.querySelectorAll('option, [data-option]');

            optionElements.forEach(function(opt) {
                var optionData = {
                    value: opt.getAttribute('value') || opt.getAttribute('data-value') || opt.textContent,
                    label: opt.getAttribute('data-label') || opt.textContent,
                    description: opt.getAttribute('data-description') || null,
                    icon: opt.getAttribute('data-icon') || null,
                    image: opt.getAttribute('data-image') || null,
                    disabled: opt.hasAttribute('disabled') || opt.getAttribute('data-disabled') === 'true',
                    selected: opt.hasAttribute('selected') || opt.getAttribute('data-selected') === 'true',
                    group: opt.getAttribute('data-group') || null
                };
                options.push(optionData);
            });

            return options;
        },

        /**
         * Create trigger button
         * @param {Object} instance
         * @returns {HTMLElement}
         */
        createTrigger: function(instance) {
            var config = instance.config;

            var trigger = document.createElement('button');
            trigger.type = 'button';
            trigger.className = 'rsl-select-trigger';
            trigger.setAttribute('aria-haspopup', 'listbox');
            trigger.setAttribute('aria-expanded', 'false');
            trigger.disabled = config.disabled;

            // Value display
            var valueDisplay = document.createElement('span');
            valueDisplay.className = 'rsl-select-value placeholder';
            valueDisplay.textContent = config.placeholder;
            trigger.appendChild(valueDisplay);
            instance.valueDisplay = valueDisplay;

            // Clear button (if clearable)
            if (config.clearable) {
                var clearBtn = document.createElement('button');
                clearBtn.type = 'button';
                clearBtn.className = 'rsl-select-clear';
                clearBtn.innerHTML = '<i class="fas fa-times"></i>';
                clearBtn.setAttribute('aria-label', 'Clear selection');
                clearBtn.setAttribute('tabindex', '-1');
                trigger.appendChild(clearBtn);
                instance.clearBtn = clearBtn;
            }

            // Arrow icon
            var arrow = document.createElement('span');
            arrow.className = 'rsl-select-arrow';
            arrow.innerHTML = '<i class="fas fa-chevron-down"></i>';
            arrow.setAttribute('aria-hidden', 'true');
            trigger.appendChild(arrow);

            return trigger;
        },

        /**
         * Create chips container for multi-select
         * @param {Object} instance
         * @returns {HTMLElement}
         */
        createChipsContainer: function(instance) {
            var container = document.createElement('div');
            container.className = 'rsl-select-chips';
            if (instance.config.showChips) {
                container.classList.add('visible');
            }
            container.setAttribute('role', 'list');
            container.setAttribute('aria-label', 'Selected items');
            return container;
        },

        /**
         * Create chips toggle button
         * @param {Object} instance
         * @returns {HTMLElement}
         */
        createChipsToggle: function(instance) {
            var button = document.createElement('button');
            button.type = 'button';
            button.className = 'rsl-select-chips-toggle';
            button.textContent = 'Show Selected';
            button.setAttribute('aria-expanded', instance.config.showChips ? 'true' : 'false');
            return button;
        },

        /**
         * Create dropdown menu
         * @param {Object} instance
         * @returns {HTMLElement}
         */
        createDropdown: function(instance) {
            var config = instance.config;
            var dropdown = document.createElement('div');
            dropdown.className = 'rsl-select-dropdown';
            dropdown.setAttribute('role', 'listbox');
            dropdown.setAttribute('aria-label', config.placeholder);
            if (config.multiSelect) {
                dropdown.setAttribute('aria-multiselectable', 'true');
            }

            // Search input (if searchable)
            if (config.searchable) {
                var searchContainer = document.createElement('div');
                searchContainer.className = 'rsl-select-search visible';

                var searchInput = document.createElement('input');
                searchInput.type = 'text';
                searchInput.placeholder = config.searchPlaceholder;
                searchInput.setAttribute('aria-label', 'Search options');
                searchInput.setAttribute('autocomplete', 'off');
                searchContainer.appendChild(searchInput);

                dropdown.appendChild(searchContainer);
                instance.searchInput = searchInput;
            }

            // Options list
            var optionsList = document.createElement('ul');
            optionsList.className = 'rsl-select-options';
            dropdown.appendChild(optionsList);
            instance.optionsList = optionsList;

            // Populate options
            RSL.Select.renderOptions(instance);

            return dropdown;
        },

        /**
         * Render options list
         * @param {Object} instance
         */
        renderOptions: function(instance) {
            var optionsList = instance.optionsList;
            var filteredOptions = instance.filteredOptions;
            var config = instance.config;

            // Clear existing options
            optionsList.innerHTML = '';

            if (filteredOptions.length === 0) {
                // No results
                var noResults = document.createElement('li');
                noResults.className = 'rsl-select-no-results';
                noResults.textContent = config.noResultsText;
                noResults.setAttribute('role', 'status');
                optionsList.appendChild(noResults);
                return;
            }

            // Group options if needed
            var groups = {};
            var ungrouped = [];

            filteredOptions.forEach(function(option) {
                if (option.group) {
                    if (!groups[option.group]) {
                        groups[option.group] = [];
                    }
                    groups[option.group].push(option);
                } else {
                    ungrouped.push(option);
                }
            });

            // Render ungrouped options first
            ungrouped.forEach(function(option, index) {
                var optionEl = RSL.Select.createOption(instance, option, index);
                optionsList.appendChild(optionEl);
            });

            // Render grouped options
            Object.keys(groups).forEach(function(groupName) {
                // Group header
                var groupHeader = document.createElement('li');
                groupHeader.className = 'rsl-select-optgroup';
                groupHeader.textContent = groupName;
                groupHeader.setAttribute('role', 'presentation');
                optionsList.appendChild(groupHeader);

                // Group options
                groups[groupName].forEach(function(option, index) {
                    var optionEl = RSL.Select.createOption(instance, option, ungrouped.length + index);
                    optionsList.appendChild(optionEl);
                });
            });
        },

        /**
         * Create a single option element
         * @param {Object} instance
         * @param {Object} optionData
         * @param {number} index
         * @returns {HTMLElement}
         */
        createOption: function(instance, optionData, index) {
            var config = instance.config;
            var li = document.createElement('li');
            li.className = 'rsl-select-option';
            li.setAttribute('role', 'option');
            li.setAttribute('data-value', optionData.value);
            li.setAttribute('data-index', index);
            li.setAttribute('tabindex', '-1');

            // Check if selected
            var isSelected = instance.selectedValues.indexOf(optionData.value) !== -1;
            if (isSelected) {
                li.classList.add('selected');
                li.setAttribute('aria-selected', 'true');
            } else {
                li.setAttribute('aria-selected', 'false');
            }

            // Disabled state
            if (optionData.disabled) {
                li.classList.add('disabled');
                li.setAttribute('aria-disabled', 'true');
            }

            // Multi-select checkbox
            if (config.multiSelect) {
                var checkbox = document.createElement('span');
                checkbox.className = 'rsl-select-checkbox';
                checkbox.setAttribute('aria-hidden', 'true');
                li.appendChild(checkbox);
            }

            // Icon or image
            if (optionData.icon || optionData.image) {
                var iconContainer = document.createElement('span');
                iconContainer.className = 'rsl-select-option-icon';

                if (optionData.image) {
                    var img = document.createElement('img');
                    img.src = optionData.image;
                    img.alt = '';
                    iconContainer.appendChild(img);
                } else if (optionData.icon) {
                    iconContainer.innerHTML = '<i class="' + optionData.icon + '"></i>';
                }

                li.appendChild(iconContainer);
            }

            // Text content
            var textContainer = document.createElement('span');
            textContainer.className = 'rsl-select-option-text';
            textContainer.textContent = optionData.label;

            // Description
            if (optionData.description) {
                var desc = document.createElement('span');
                desc.className = 'rsl-select-option-description';
                desc.textContent = optionData.description;
                textContainer.appendChild(desc);
            }

            li.appendChild(textContainer);

            // Checkmark for single select
            if (!config.multiSelect) {
                var checkmark = document.createElement('span');
                checkmark.className = 'rsl-select-checkmark';
                checkmark.innerHTML = '<i class="fas fa-check"></i>';
                checkmark.setAttribute('aria-hidden', 'true');
                li.appendChild(checkmark);
            }

            // ARIA label
            var ariaLabel = optionData.label;
            if (optionData.description) {
                ariaLabel += ', ' + optionData.description;
            }
            if (isSelected) {
                ariaLabel += ', selected';
            }
            if (optionData.disabled) {
                ariaLabel += ', disabled';
            }
            li.setAttribute('aria-label', ariaLabel);

            return li;
        },

        /**
         * Create hidden select for form submission
         * @param {Object} instance
         * @returns {HTMLElement}
         */
        createHiddenSelect: function(instance) {
            var select = document.createElement('select');
            select.name = instance.config.name;
            select.className = 'rsl-select-sr-only';
            select.setAttribute('aria-hidden', 'true');
            select.setAttribute('tabindex', '-1');

            if (instance.config.multiSelect) {
                select.setAttribute('multiple', '');
            }

            if (instance.config.required) {
                select.setAttribute('required', '');
            }

            return select;
        },

        /**
         * Attach event listeners
         * @param {Object} instance
         */
        attachEvents: function(instance) {
            var trigger = instance.trigger;
            var dropdown = instance.dropdown;
            var searchInput = instance.searchInput;
            var clearBtn = instance.clearBtn;
            var chipsToggle = instance.chipsToggle;
            var optionsList = instance.optionsList;

            // Toggle dropdown on trigger click
            trigger.addEventListener('click', function(e) {
                e.preventDefault();
                e.stopPropagation();
                RSL.Select.toggle(instance);
            });

            // Clear button
            if (clearBtn) {
                clearBtn.addEventListener('click', function(e) {
                    e.preventDefault();
                    e.stopPropagation();
                    RSL.Select.clear(instance);
                });
            }

            // Chips toggle
            if (chipsToggle) {
                chipsToggle.addEventListener('click', function(e) {
                    e.preventDefault();
                    RSL.Select.toggleChips(instance);
                });
            }

            // Search input
            if (searchInput) {
                searchInput.addEventListener('input', function(e) {
                    RSL.Select.filter(instance, e.target.value);
                });

                // Prevent dropdown close on search input click
                searchInput.addEventListener('click', function(e) {
                    e.stopPropagation();
                });
            }

            // Option selection
            optionsList.addEventListener('click', function(e) {
                var option = e.target.closest('.rsl-select-option');
                if (option && !option.classList.contains('disabled')) {
                    var value = option.getAttribute('data-value');
                    RSL.Select.selectOption(instance, value);
                }
            });

            // Keyboard navigation on trigger
            trigger.addEventListener('keydown', function(e) {
                RSL.Select.handleTriggerKeydown(instance, e);
            });

            // Keyboard navigation in dropdown
            dropdown.addEventListener('keydown', function(e) {
                RSL.Select.handleDropdownKeydown(instance, e);
            });

            // Close on outside click
            document.addEventListener('click', function(e) {
                if (!instance.wrapper.contains(e.target)) {
                    RSL.Select.close(instance);
                }
            });

            // Close on escape
            document.addEventListener('keydown', function(e) {
                if (e.key === 'Escape' && instance.isOpen) {
                    RSL.Select.close(instance);
                    trigger.focus();
                }
            });

            // Set initial selections
            var initialSelections = instance.allOptions.filter(function(opt) {
                return opt.selected;
            });

            initialSelections.forEach(function(opt) {
                RSL.Select.selectOption(instance, opt.value, true);
            });
        },

        /**
         * Toggle dropdown open/closed
         * @param {Object} instance
         */
        toggle: function(instance) {
            if (instance.isOpen) {
                RSL.Select.close(instance);
            } else {
                RSL.Select.open(instance);
            }
        },

        /**
         * Open dropdown
         * @param {Object} instance
         */
        open: function(instance) {
            if (instance.config.disabled) return;

            instance.isOpen = true;
            instance.wrapper.classList.add('open');
            instance.trigger.setAttribute('aria-expanded', 'true');

            // Position dropdown
            RSL.Select.positionDropdown(instance);

            // Focus search input or first option
            setTimeout(function() {
                if (instance.searchInput) {
                    instance.searchInput.focus();
                } else {
                    RSL.Select.focusOption(instance, 0);
                }
            }, 100);

            // Callback
            if (instance.config.onOpen && typeof window[instance.config.onOpen] === 'function') {
                window[instance.config.onOpen](instance);
            }
        },

        /**
         * Close dropdown
         * @param {Object} instance
         */
        close: function(instance) {
            instance.isOpen = false;
            instance.wrapper.classList.remove('open');
            instance.trigger.setAttribute('aria-expanded', 'false');
            instance.focusedIndex = -1;

            // Clear search
            if (instance.searchInput) {
                instance.searchInput.value = '';
                RSL.Select.filter(instance, '');
            }

            // Remove focused class from options
            var options = instance.optionsList.querySelectorAll('.rsl-select-option');
            options.forEach(function(opt) {
                opt.classList.remove('focused');
            });

            // Callback
            if (instance.config.onClose && typeof window[instance.config.onClose] === 'function') {
                window[instance.config.onClose](instance);
            }
        },

        /**
         * Position dropdown (above or below trigger)
         * @param {Object} instance
         */
        positionDropdown: function(instance) {
            var config = instance.config;
            var trigger = instance.trigger;
            var dropdown = instance.dropdown;

            if (config.position === 'above') {
                dropdown.classList.add('open-above');
                return;
            }

            if (config.position === 'below') {
                dropdown.classList.remove('open-above');
                return;
            }

            // Auto positioning
            var rect = trigger.getBoundingClientRect();
            var spaceBelow = window.innerHeight - rect.bottom;
            var spaceAbove = rect.top;
            var dropdownHeight = 300; // approximate

            if (spaceBelow < dropdownHeight && spaceAbove > spaceBelow) {
                dropdown.classList.add('open-above');
            } else {
                dropdown.classList.remove('open-above');
            }
        },

        /**
         * Select/deselect an option
         * @param {Object} instance
         * @param {string} value
         * @param {boolean} silent - Don't trigger change event
         */
        selectOption: function(instance, value, silent) {
            var config = instance.config;
            var index = instance.selectedValues.indexOf(value);

            if (config.multiSelect) {
                // Multi-select: toggle selection
                if (index !== -1) {
                    // Deselect
                    instance.selectedValues.splice(index, 1);
                } else {
                    // Check max selections
                    if (instance.selectedValues.length >= config.maxSelections) {
                        return;
                    }
                    // Select
                    instance.selectedValues.push(value);
                }
            } else {
                // Single select: replace selection
                instance.selectedValues = [value];
                RSL.Select.close(instance);
            }

            // Update UI
            RSL.Select.updateUI(instance);

            // Trigger change event
            if (!silent) {
                RSL.Select.triggerChange(instance);
            }
        },

        /**
         * Clear all selections
         * @param {Object} instance
         */
        clear: function(instance) {
            instance.selectedValues = [];
            RSL.Select.updateUI(instance);
            RSL.Select.triggerChange(instance);
            instance.trigger.focus();
        },

        /**
         * Filter options by search term
         * @param {Object} instance
         * @param {string} searchTerm
         */
        filter: function(instance, searchTerm) {
            var term = searchTerm.toLowerCase().trim();

            if (!term) {
                instance.filteredOptions = instance.allOptions.slice();
            } else {
                instance.filteredOptions = instance.allOptions.filter(function(option) {
                    var label = option.label.toLowerCase();
                    var description = (option.description || '').toLowerCase();
                    return label.indexOf(term) !== -1 || description.indexOf(term) !== -1;
                });
            }

            // Re-render options
            RSL.Select.renderOptions(instance);

            // Reset focus
            instance.focusedIndex = -1;
            RSL.Select.focusOption(instance, 0);
        },

        /**
         * Toggle chips visibility
         * @param {Object} instance
         */
        toggleChips: function(instance) {
            var chipsContainer = instance.chipsContainer;
            var chipsToggle = instance.chipsToggle;
            var isVisible = chipsContainer.classList.contains('visible');

            if (isVisible) {
                chipsContainer.classList.remove('visible');
                chipsToggle.textContent = 'Show Selected';
                chipsToggle.setAttribute('aria-expanded', 'false');
            } else {
                chipsContainer.classList.add('visible');
                chipsToggle.textContent = 'Hide Selected';
                chipsToggle.setAttribute('aria-expanded', 'true');
            }
        },

        /**
         * Update all UI elements after selection change
         * @param {Object} instance
         */
        updateUI: function(instance) {
            var config = instance.config;
            var selectedValues = instance.selectedValues;

            // Update trigger display
            RSL.Select.updateTriggerDisplay(instance);

            // Update option states
            var options = instance.optionsList.querySelectorAll('.rsl-select-option');
            options.forEach(function(opt) {
                var value = opt.getAttribute('data-value');
                var isSelected = selectedValues.indexOf(value) !== -1;

                if (isSelected) {
                    opt.classList.add('selected');
                    opt.setAttribute('aria-selected', 'true');
                } else {
                    opt.classList.remove('selected');
                    opt.setAttribute('aria-selected', 'false');
                }

                // Update ARIA label
                var label = opt.querySelector('.rsl-select-option-text').textContent;
                var ariaLabel = label;
                if (isSelected) ariaLabel += ', selected';
                opt.setAttribute('aria-label', ariaLabel);
            });

            // Update chips
            if (config.multiSelect) {
                RSL.Select.updateChips(instance);
            }

            // Update hidden select
            if (instance.hiddenSelect) {
                RSL.Select.updateHiddenSelect(instance);
            }

            // Update clearable state
            if (config.clearable) {
                if (selectedValues.length > 0) {
                    instance.wrapper.classList.add('has-value');
                } else {
                    instance.wrapper.classList.remove('has-value');
                }
            }
        },

        /**
         * Update trigger display text
         * @param {Object} instance
         */
        updateTriggerDisplay: function(instance) {
            var config = instance.config;
            var selectedValues = instance.selectedValues;
            var valueDisplay = instance.valueDisplay;

            if (selectedValues.length === 0) {
                valueDisplay.textContent = config.placeholder;
                valueDisplay.classList.add('placeholder');
                return;
            }

            valueDisplay.classList.remove('placeholder');

            if (config.multiSelect) {
                // Multi-select: show count or first item
                if (config.showCount) {
                    var countText = selectedValues.length === 1
                        ? '1 item selected'
                        : selectedValues.length + ' items selected';
                    valueDisplay.innerHTML = countText;
                } else {
                    var firstOption = instance.allOptions.find(function(opt) {
                        return opt.value === selectedValues[0];
                    });
                    var text = firstOption ? firstOption.label : selectedValues[0];
                    if (selectedValues.length > 1) {
                        text += ' <span class="rsl-select-count">+' + (selectedValues.length - 1) + '</span>';
                    }
                    valueDisplay.innerHTML = text;
                }
            } else {
                // Single select: show selected option label
                var selectedOption = instance.allOptions.find(function(opt) {
                    return opt.value === selectedValues[0];
                });
                valueDisplay.textContent = selectedOption ? selectedOption.label : selectedValues[0];
            }
        },

        /**
         * Update chips display
         * @param {Object} instance
         */
        updateChips: function(instance) {
            var chipsContainer = instance.chipsContainer;
            var selectedValues = instance.selectedValues;

            // Clear existing chips
            chipsContainer.innerHTML = '';

            // Create chip for each selection
            selectedValues.forEach(function(value) {
                var option = instance.allOptions.find(function(opt) {
                    return opt.value === value;
                });

                if (option) {
                    var chip = document.createElement('div');
                    chip.className = 'rsl-select-chip';
                    chip.setAttribute('role', 'listitem');

                    var label = document.createElement('span');
                    label.textContent = option.label;
                    chip.appendChild(label);

                    var removeBtn = document.createElement('button');
                    removeBtn.type = 'button';
                    removeBtn.className = 'rsl-select-chip-remove';
                    removeBtn.innerHTML = '×';
                    removeBtn.setAttribute('aria-label', 'Remove ' + option.label);
                    removeBtn.addEventListener('click', function(e) {
                        e.preventDefault();
                        e.stopPropagation();
                        RSL.Select.selectOption(instance, value);
                    });
                    chip.appendChild(removeBtn);

                    chipsContainer.appendChild(chip);
                }
            });
        },

        /**
         * Update hidden select element
         * @param {Object} instance
         */
        updateHiddenSelect: function(instance) {
            var select = instance.hiddenSelect;
            var selectedValues = instance.selectedValues;

            // Clear existing options
            select.innerHTML = '';

            // Add selected options
            selectedValues.forEach(function(value) {
                var option = document.createElement('option');
                option.value = value;
                option.selected = true;
                select.appendChild(option);
            });

            // Add empty option if nothing selected (for validation)
            if (selectedValues.length === 0 && instance.config.required) {
                var emptyOption = document.createElement('option');
                emptyOption.value = '';
                emptyOption.selected = true;
                select.appendChild(emptyOption);
            }
        },

        /**
         * Focus an option by index
         * @param {Object} instance
         * @param {number} index
         */
        focusOption: function(instance, index) {
            var options = instance.optionsList.querySelectorAll('.rsl-select-option:not(.disabled)');
            if (options.length === 0) return;

            // Clamp index
            if (index < 0) index = 0;
            if (index >= options.length) index = options.length - 1;

            // Remove previous focus
            options.forEach(function(opt) {
                opt.classList.remove('focused');
            });

            // Add focus to new option
            var targetOption = options[index];
            targetOption.classList.add('focused');
            targetOption.focus();

            // Scroll into view
            targetOption.scrollIntoView({ block: 'nearest', behavior: 'smooth' });

            instance.focusedIndex = index;
        },

        /**
         * Handle keyboard navigation on trigger
         * @param {Object} instance
         * @param {KeyboardEvent} e
         */
        handleTriggerKeydown: function(instance, e) {
            switch (e.key) {
                case 'Enter':
                case ' ':
                case 'ArrowDown':
                case 'ArrowUp':
                    e.preventDefault();
                    if (!instance.isOpen) {
                        RSL.Select.open(instance);
                    }
                    break;
                case 'Escape':
                    if (instance.isOpen) {
                        e.preventDefault();
                        RSL.Select.close(instance);
                    }
                    break;
            }
        },

        /**
         * Handle keyboard navigation in dropdown
         * @param {Object} instance
         * @param {KeyboardEvent} e
         */
        handleDropdownKeydown: function(instance, e) {
            var options = instance.optionsList.querySelectorAll('.rsl-select-option:not(.disabled)');

            switch (e.key) {
                case 'ArrowDown':
                    e.preventDefault();
                    RSL.Select.focusOption(instance, instance.focusedIndex + 1);
                    break;

                case 'ArrowUp':
                    e.preventDefault();
                    RSL.Select.focusOption(instance, instance.focusedIndex - 1);
                    break;

                case 'Home':
                    e.preventDefault();
                    RSL.Select.focusOption(instance, 0);
                    break;

                case 'End':
                    e.preventDefault();
                    RSL.Select.focusOption(instance, options.length - 1);
                    break;

                case 'Enter':
                case ' ':
                    e.preventDefault();
                    if (instance.focusedIndex !== -1 && options[instance.focusedIndex]) {
                        var value = options[instance.focusedIndex].getAttribute('data-value');
                        RSL.Select.selectOption(instance, value);
                    }
                    break;

                case 'Escape':
                    e.preventDefault();
                    RSL.Select.close(instance);
                    instance.trigger.focus();
                    break;

                case 'Tab':
                    RSL.Select.close(instance);
                    break;

                default:
                    // Type-ahead search
                    if (e.key.length === 1 && !instance.searchInput) {
                        RSL.Select.typeAheadSearch(instance, e.key);
                    }
                    break;
            }
        },

        /**
         * Type-ahead search (when no search input)
         * @param {Object} instance
         * @param {string} char
         */
        typeAheadSearch: function(instance, char) {
            var options = instance.optionsList.querySelectorAll('.rsl-select-option:not(.disabled)');
            var searchChar = char.toLowerCase();

            // Find next option starting with character
            var startIndex = instance.focusedIndex + 1;
            for (var i = 0; i < options.length; i++) {
                var index = (startIndex + i) % options.length;
                var option = options[index];
                var label = option.querySelector('.rsl-select-option-text').textContent;

                if (label.toLowerCase().startsWith(searchChar)) {
                    RSL.Select.focusOption(instance, index);
                    break;
                }
            }
        },

        /**
         * Trigger change event and callback
         * @param {Object} instance
         */
        triggerChange: function(instance) {
            var config = instance.config;

            // Dispatch custom event
            var event = new CustomEvent('rsl-select-change', {
                detail: {
                    values: instance.selectedValues,
                    options: instance.selectedValues.map(function(value) {
                        return instance.allOptions.find(function(opt) {
                            return opt.value === value;
                        });
                    })
                }
            });
            instance.element.dispatchEvent(event);

            // Call callback function
            if (config.onChange && typeof window[config.onChange] === 'function') {
                window[config.onChange](instance.selectedValues, instance);
            }

            // Trigger form validation if present
            if (instance.hiddenSelect && window.RSL && window.RSL.FormValidation) {
                window.RSL.FormValidation.validateField(instance.hiddenSelect);
            }

            // Publish to FilterBus (if configured)
            RSL.Select.publishToFilterBus(instance);
        },

        /**
         * Get selected values
         * @param {HTMLElement} element
         * @returns {Array}
         */
        getValue: function(element) {
            var instance = RSL.Select.instances.get(element);
            return instance ? instance.selectedValues : [];
        },

        /**
         * Set selected values programmatically
         * @param {HTMLElement} element
         * @param {Array|string} values
         */
        setValue: function(element, values) {
            var instance = RSL.Select.instances.get(element);
            if (!instance) return;

            // Convert single value to array
            if (typeof values === 'string') {
                values = [values];
            }

            instance.selectedValues = values;
            RSL.Select.updateUI(instance);
            RSL.Select.triggerChange(instance);
        },

        /**
         * Destroy select instance
         * @param {HTMLElement} element
         */
        destroy: function(element) {
            var instance = RSL.Select.instances.get(element);
            if (!instance) return;

            // Unsubscribe from FilterBus
            var subscriberId = RSL.Select.filterSubscriptions.get(element);
            if (subscriberId && window.RSL && window.RSL.FilterBus && window.RSL.FilterBus.unsubscribe) {
                window.RSL.FilterBus.unsubscribe(subscriberId);
            }
            RSL.Select.filterSubscriptions.delete(element);

            // Remove wrapper
            instance.wrapper.parentNode.replaceChild(element, instance.wrapper);
            element.style.display = '';

            // Remove instance
            RSL.Select.instances.delete(element);
        },

        /* ============================================
           FILTERBUS INTEGRATION
           ============================================ */

        /**
         * Setup FilterBus subscription for a select
         * Bidirectional: can publish changes AND subscribe to state
         * @param {Object} instance - Select instance
         */
        setupFilterBus: function(instance) {
            var config = instance.config;
            var element = instance.element;

            // Check if FilterBus is available
            if (!window.RSL || !window.RSL.FilterBus) {
                return;
            }

            // Subscribe to FilterBus state changes
            if (config.filterBusSubscribe) {
                var subscriberId = 'select-' + (element.id || Math.random().toString(36).substr(2, 9));

                window.RSL.FilterBus.subscribe(
                    subscriberId,
                    function(state, meta) {
                        RSL.Select.handleFilterBusChange(instance, state, meta);
                    },
                    { keys: [config.filterBusSubscribe] }
                );

                // Store subscription ID for cleanup
                RSL.Select.filterSubscriptions.set(element, subscriberId);

                // Apply any existing FilterBus state on init
                var currentState = window.RSL.FilterBus.getState();
                if (Object.keys(currentState).length > 0) {
                    RSL.Select.handleFilterBusChange(instance, currentState, { source: 'init' });
                }
            }

            // Add initialized class after brief delay (prevents transition flicker)
            setTimeout(function() {
                if (instance.wrapper) {
                    instance.wrapper.classList.add('rsl-select-filterbus-initialized');
                }
            }, 50);
        },

        /**
         * Handle FilterBus state changes
         * Can update selection OR control visibility based on configuration
         * @param {Object} instance - Select instance
         * @param {Object} state - Current filter state
         * @param {Object} meta - Change metadata
         */
        handleFilterBusChange: function(instance, state, meta) {
            var config = instance.config;

            if (!state || !config.filterBusSubscribe) return;

            var filterKey = config.filterBusSubscribe;
            var filterValue = state[filterKey];

            // If this select has a filter-value, use visibility mode
            if (config.filterValue !== null) {
                RSL.Select.handleVisibilityFilter(instance, filterValue);
                return;
            }

            // Otherwise, update selection to match filter state
            if (filterValue !== undefined && filterValue !== null) {
                // Find matching option
                var matchingOption = instance.allOptions.find(function(opt) {
                    return String(opt.value).toLowerCase() === String(filterValue).toLowerCase();
                });

                if (matchingOption) {
                    // Update selection without triggering publish (prevent loop)
                    instance._skipPublish = true;
                    RSL.Select.setValue(instance.element, matchingOption.value);
                    instance._skipPublish = false;
                }
            }

            // Dispatch event
            instance.element.dispatchEvent(new CustomEvent('rsl-select:filterbus-update', {
                bubbles: true,
                detail: { state: state, meta: meta }
            }));
        },

        /**
         * Handle visibility-based filtering
         * Shows/hides select based on filter match
         * @param {Object} instance - Select instance
         * @param {*} filterValue - Current filter value
         */
        handleVisibilityFilter: function(instance, filterValue) {
            var config = instance.config;
            var wrapper = instance.wrapper;
            var componentValue = config.filterValue;

            var shouldShow = true;

            if (filterValue !== undefined && filterValue !== null && filterValue !== '') {
                var filterLower = String(filterValue).toLowerCase();

                if (filterLower === 'all') {
                    shouldShow = true;
                } else if (componentValue !== undefined && componentValue !== null) {
                    var componentValues = String(componentValue).split(',').map(function(v) {
                        return v.trim().toLowerCase();
                    });
                    shouldShow = componentValues.includes(filterLower);
                }
            }

            // Apply visibility
            if (shouldShow) {
                wrapper.classList.remove('rsl-select-filterbus-hidden');
                wrapper.removeAttribute('aria-hidden');
            } else {
                wrapper.classList.add('rsl-select-filterbus-hidden');
                wrapper.setAttribute('aria-hidden', 'true');
            }
        },

        /**
         * Publish selection change to FilterBus
         * @param {Object} instance - Select instance
         */
        publishToFilterBus: function(instance) {
            var config = instance.config;

            // Skip if no publish key or during subscription update
            if (!config.filterBusPublish || instance._skipPublish) return;

            // Check if FilterBus is available
            if (!window.RSL || !window.RSL.FilterBus) return;

            // Get selected value (use first value for single select, array for multi)
            var value = config.multiSelect
                ? instance.selectedValues
                : (instance.selectedValues[0] || '');

            // Publish to FilterBus
            window.RSL.FilterBus.publish(config.filterBusPublish, value, {
                source: 'select',
                elementId: instance.element.id || null
            });
        },

        /**
         * Initialize FilterBus for an existing select element
         * @param {HTMLElement} element - The select element
         */
        initFilterBus: function(element) {
            var instance = RSL.Select.instances.get(element);
            if (instance) {
                RSL.Select.setupFilterBus(instance);
            }
        },

        /**
         * Destroy FilterBus subscription for a select
         * @param {HTMLElement} element - The select element
         */
        destroyFilterBus: function(element) {
            var subscriberId = RSL.Select.filterSubscriptions.get(element);
            if (subscriberId && window.RSL && window.RSL.FilterBus && window.RSL.FilterBus.unsubscribe) {
                window.RSL.FilterBus.unsubscribe(subscriberId);
            }
            RSL.Select.filterSubscriptions.delete(element);

            var instance = RSL.Select.instances.get(element);
            if (instance && instance.wrapper) {
                instance.wrapper.classList.remove('rsl-select-filterbus-initialized');
                instance.wrapper.classList.remove('rsl-select-filterbus-hidden');
            }
        }
    };

    /**
     * Auto-initialize on DOM ready
     */
    document.addEventListener('DOMContentLoaded', function() {
        RSL.Select.init();
    });

})();
