/* ============================================
   RSL Time Picker Component
   Version: 1.0.0
   Description: Premium accessible time picker with
   single time and time range selection modes.
   Full ADA/WCAG 2.1 AA compliant with keyboard navigation,
   screen reader support, and live announcements.
   Features clock dial, quick presets, and natural typing.

   FilterBus Integration:
   - Publishes time selection to FilterBus for cross-component filtering
   - Use data-filterbus-publish="key" to enable publishing
   ============================================ */

(function() {
    'use strict';

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

    /**
     * Time Picker Component
     * A fully accessible time picker supporting single and range selection modes
     */
    window.RSL.TimePicker = {

        /** Store all initialized instances */
        instances: new Map(),

        /** Default configuration */
        defaults: {
            mode: 'single',              // 'single' or 'range'
            format: '12',                // '12' (AM/PM) or '24'
            step: 5,                     // Minute increment (1, 5, 15, 30, 60)
            minTime: null,               // Minimum time 'HH:mm'
            maxTime: null,               // Maximum time 'HH:mm'
            defaultTime: null,           // Initial time or 'now'
            showPresets: true,           // Show quick preset buttons
            showDial: true,              // Show clock dial (false = list only)
            inline: false,               // Always visible (no popover)
            clearable: true,             // Allow clearing selection
            closeOnSelect: false,        // Close after selection (single mode) - default false for better UX
            autoApply: true,             // Auto-apply without confirm button
            required: false,
            disabled: false,
            readOnly: false,
            placeholder: 'Select time',
            placeholderStart: 'Start time',
            placeholderEnd: 'End time',
            ariaLabel: 'Select time',
            ariaLabelStart: 'Start time',
            ariaLabelEnd: 'End time'
        },

        /** Quick preset definitions */
        presets: {
            now: {
                label: 'Now',
                getTime: function() {
                    var now = new Date();
                    return { hours: now.getHours(), minutes: now.getMinutes() };
                }
            },
            morning: {
                label: 'Morning',
                getTime: function() {
                    return { hours: 9, minutes: 0 };
                }
            },
            noon: {
                label: 'Noon',
                getTime: function() {
                    return { hours: 12, minutes: 0 };
                }
            },
            afternoon: {
                label: 'Afternoon',
                getTime: function() {
                    return { hours: 14, minutes: 0 };
                }
            },
            evening: {
                label: 'Evening',
                getTime: function() {
                    return { hours: 18, minutes: 0 };
                }
            },
            endOfDay: {
                label: 'End of Day',
                getTime: function() {
                    return { hours: 17, minutes: 0 };
                }
            }
        },

        /**
         * Initialize all time pickers on the page
         */
        init: function() {
            var self = this;
            var elements = document.querySelectorAll('[data-rsl-time-picker]');

            elements.forEach(function(element) {
                if (!self.instances.has(element)) {
                    self.create(element);
                }
            });

            return this;
        },

        /**
         * Create a time picker instance
         * @param {HTMLElement|string} element - Element or selector
         * @param {Object} options - Configuration options
         */
        create: function(element, options) {
            var self = this;

            // Handle string selector
            if (typeof element === 'string') {
                element = document.querySelector(element);
            }

            if (!element) {
                console.warn('RSL TimePicker: Element not found');
                return null;
            }

            // Don't reinitialize
            if (this.instances.has(element)) {
                return this.instances.get(element);
            }

            // Parse configuration from data attributes and options
            var config = this._parseConfig(element, options);

            // Create instance object
            var instance = {
                element: element,
                config: config,
                isOpen: false,
                selectedHours: null,
                selectedMinutes: null,
                selectedPeriod: 'AM',
                activeSegment: 'hours', // 'hours', 'minutes', 'period'
                rangeStart: null,
                rangeEnd: null,
                selectingStart: true,
                dom: {}
            };

            // Build the picker UI
            this._buildUI(instance);

            // Set initial value if provided
            if (config.defaultTime) {
                this._setInitialValue(instance, config.defaultTime);
            }

            // Attach event listeners
            this._attachEvents(instance);

            // Store instance
            this.instances.set(element, instance);

            // Apply disabled/readonly states
            if (config.disabled) {
                this._setDisabled(instance, true);
            }
            if (config.readOnly) {
                this._setReadOnly(instance, true);
            }

            return instance;
        },

        /**
         * Parse configuration from data attributes and options
         */
        _parseConfig: function(element, options) {
            var config = Object.assign({}, this.defaults);

            // Parse data attributes
            var dataset = element.dataset;

            if (dataset.mode) config.mode = dataset.mode;
            if (dataset.format) config.format = dataset.format;
            if (dataset.step) config.step = parseInt(dataset.step, 10);
            if (dataset.minTime) config.minTime = dataset.minTime;
            if (dataset.maxTime) config.maxTime = dataset.maxTime;
            if (dataset.defaultTime) config.defaultTime = dataset.defaultTime;
            if (dataset.showPresets !== undefined) config.showPresets = dataset.showPresets !== 'false';
            if (dataset.showDial !== undefined) config.showDial = dataset.showDial !== 'false';
            if (dataset.inline !== undefined) config.inline = dataset.inline === 'true';
            if (dataset.clearable !== undefined) config.clearable = dataset.clearable !== 'false';
            if (dataset.closeOnSelect !== undefined) config.closeOnSelect = dataset.closeOnSelect !== 'false';
            if (dataset.autoApply !== undefined) config.autoApply = dataset.autoApply !== 'false';
            if (dataset.required !== undefined) config.required = dataset.required === 'true';
            if (dataset.disabled !== undefined) config.disabled = dataset.disabled === 'true';
            if (dataset.readOnly !== undefined) config.readOnly = dataset.readOnly === 'true';
            if (dataset.placeholder) config.placeholder = dataset.placeholder;
            if (dataset.placeholderStart) config.placeholderStart = dataset.placeholderStart;
            if (dataset.placeholderEnd) config.placeholderEnd = dataset.placeholderEnd;
            if (dataset.ariaLabel) config.ariaLabel = dataset.ariaLabel;
            if (dataset.filterbusPublish) config.filterBusKey = dataset.filterbusPublish;

            // Merge with passed options
            if (options) {
                Object.assign(config, options);
            }

            return config;
        },

        /**
         * Build the picker UI
         */
        _buildUI: function(instance) {
            var self = this;
            var el = instance.element;
            var config = instance.config;

            // Create wrapper
            var wrapper = document.createElement('div');
            wrapper.className = 'rsl-time-picker';
            if (config.mode === 'range') {
                wrapper.setAttribute('data-mode', 'range');
            }
            if (config.inline) {
                wrapper.classList.add('inline');
            }

            // Create live region for screen reader announcements
            var liveRegion = document.createElement('div');
            liveRegion.className = 'rsl-time-picker-live';
            liveRegion.setAttribute('role', 'status');
            liveRegion.setAttribute('aria-live', 'polite');
            liveRegion.setAttribute('aria-atomic', 'true');
            wrapper.appendChild(liveRegion);
            instance.dom.liveRegion = liveRegion;

            // Build input(s)
            var inputWrapper = document.createElement('div');
            inputWrapper.className = 'rsl-time-picker-wrapper';

            if (config.mode === 'single') {
                inputWrapper.appendChild(this._createInputField(instance, 'single'));
            } else {
                inputWrapper.appendChild(this._createInputField(instance, 'start'));

                var separator = document.createElement('span');
                separator.className = 'rsl-time-picker-separator';
                separator.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M5 12h14M12 5l7 7-7 7"/></svg>';
                separator.setAttribute('aria-hidden', 'true');
                inputWrapper.appendChild(separator);

                inputWrapper.appendChild(this._createInputField(instance, 'end'));
            }

            wrapper.appendChild(inputWrapper);
            instance.dom.inputWrapper = inputWrapper;

            // Build popover
            var popover = this._buildPopover(instance);
            wrapper.appendChild(popover);
            instance.dom.popover = popover;

            // Apply FilterBus attribute if configured
            if (config.filterBusKey) {
                wrapper.setAttribute('data-filterbus-publish', config.filterBusKey);
            }

            // Replace original element or wrap it
            if (el.tagName === 'INPUT') {
                // If original is an input, preserve its value
                var originalValue = el.value;
                el.parentNode.insertBefore(wrapper, el);
                el.style.display = 'none';
                wrapper.appendChild(el);
                instance.dom.originalInput = el;

                // Set initial value from original input
                if (originalValue && !config.defaultTime) {
                    config.defaultTime = originalValue;
                }
            } else {
                el.appendChild(wrapper);
            }

            instance.dom.wrapper = wrapper;
        },

        /**
         * Create an input field
         */
        _createInputField: function(instance, type) {
            var config = instance.config;
            var field = document.createElement('div');
            field.className = 'rsl-time-picker-field';

            var inputGroup = document.createElement('div');
            inputGroup.className = 'rsl-time-picker-input-group';

            // Create input
            var input = document.createElement('input');
            input.type = 'text';
            input.className = 'rsl-time-picker-input';
            input.readOnly = true; // Prevent direct editing, use popover

            var placeholder, ariaLabel, inputId;
            if (type === 'single') {
                placeholder = config.placeholder;
                ariaLabel = config.ariaLabel;
                inputId = 'rsl-tp-' + this._generateId();
            } else if (type === 'start') {
                placeholder = config.placeholderStart;
                ariaLabel = config.ariaLabelStart;
                inputId = 'rsl-tp-start-' + this._generateId();
            } else {
                placeholder = config.placeholderEnd;
                ariaLabel = config.ariaLabelEnd;
                inputId = 'rsl-tp-end-' + this._generateId();
            }

            input.id = inputId;
            input.placeholder = placeholder;
            input.setAttribute('aria-label', ariaLabel);
            input.setAttribute('aria-haspopup', 'dialog');
            input.setAttribute('aria-expanded', 'false');
            input.setAttribute('autocomplete', 'off');

            if (config.required) {
                input.setAttribute('aria-required', 'true');
            }

            inputGroup.appendChild(input);

            // Clear button
            if (config.clearable) {
                var clearBtn = document.createElement('button');
                clearBtn.type = 'button';
                clearBtn.className = 'rsl-time-picker-clear';
                clearBtn.setAttribute('aria-label', 'Clear time');
                clearBtn.setAttribute('tabindex', '-1');
                clearBtn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6L6 18M6 6l12 12"/></svg>';
                inputGroup.appendChild(clearBtn);

                if (type === 'single' || type === 'start') {
                    instance.dom.clearBtn = clearBtn;
                } else {
                    instance.dom.clearBtnEnd = clearBtn;
                }
            }

            // Clock icon
            var icon = document.createElement('span');
            icon.className = 'rsl-time-picker-icon';
            icon.setAttribute('aria-hidden', 'true');
            icon.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>';
            inputGroup.appendChild(icon);

            field.appendChild(inputGroup);

            // Store references
            if (type === 'single' || type === 'start') {
                instance.dom.input = input;
                instance.dom.inputField = field;
            } else {
                instance.dom.inputEnd = input;
                instance.dom.inputFieldEnd = field;
            }

            return field;
        },

        /**
         * Build the popover
         */
        _buildPopover: function(instance) {
            var self = this;
            var config = instance.config;

            var popover = document.createElement('div');
            popover.className = 'rsl-time-picker-popover';
            popover.setAttribute('role', 'dialog');
            popover.setAttribute('aria-modal', 'true');
            popover.setAttribute('aria-label', 'Time picker');

            // Header with time display and close button
            var header = document.createElement('div');
            header.className = 'rsl-time-picker-header';
            header.appendChild(this._buildTimeDisplay(instance));

            // Close button
            var closeBtn = document.createElement('button');
            closeBtn.type = 'button';
            closeBtn.className = 'rsl-time-picker-close';
            closeBtn.setAttribute('aria-label', 'Close time picker');
            closeBtn.innerHTML = '<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>';
            header.appendChild(closeBtn);
            instance.dom.closeBtn = closeBtn;

            popover.appendChild(header);
            instance.dom.header = header;

            // Main content area - either dial or list
            if (config.showDial) {
                var dial = this._buildClockDial(instance);
                popover.appendChild(dial);
                instance.dom.dial = dial;
            } else {
                var lists = this._buildLists(instance);
                popover.appendChild(lists);
                instance.dom.lists = lists;
            }

            // Presets
            if (config.showPresets) {
                var presets = this._buildPresets(instance);
                popover.appendChild(presets);
                instance.dom.presets = presets;
            }

            // Footer with actions (if not auto-apply)
            if (!config.autoApply) {
                var footer = this._buildFooter(instance);
                popover.appendChild(footer);
                instance.dom.footer = footer;
            }

            return popover;
        },

        /**
         * Build the time display in header
         */
        _buildTimeDisplay: function(instance) {
            var self = this;
            var config = instance.config;
            var is12Hour = config.format === '12';

            var display = document.createElement('div');
            display.className = 'rsl-time-picker-display';

            // Hours segment
            var hoursBtn = document.createElement('button');
            hoursBtn.type = 'button';
            hoursBtn.className = 'rsl-time-picker-display-segment active';
            hoursBtn.setAttribute('data-segment', 'hours');
            hoursBtn.setAttribute('aria-label', 'Hours. Press up or down to change.');
            hoursBtn.textContent = '--';
            display.appendChild(hoursBtn);
            instance.dom.hoursDisplay = hoursBtn;

            // Colon
            var colon = document.createElement('span');
            colon.className = 'rsl-time-picker-display-colon';
            colon.textContent = ':';
            colon.setAttribute('aria-hidden', 'true');
            display.appendChild(colon);

            // Minutes segment
            var minutesBtn = document.createElement('button');
            minutesBtn.type = 'button';
            minutesBtn.className = 'rsl-time-picker-display-segment';
            minutesBtn.setAttribute('data-segment', 'minutes');
            minutesBtn.setAttribute('aria-label', 'Minutes. Press up or down to change.');
            minutesBtn.textContent = '--';
            display.appendChild(minutesBtn);
            instance.dom.minutesDisplay = minutesBtn;

            // AM/PM buttons - always create, but hide initially for 24-hour format
            // In 24-hour mode, show when ambiguous hour (1-11) is selected
            var period = document.createElement('div');
            period.className = 'rsl-time-picker-period';
            if (!is12Hour) {
                period.style.display = 'none'; // Hidden by default in 24-hour mode
            }

            var amBtn = document.createElement('button');
            amBtn.type = 'button';
            amBtn.className = 'rsl-time-picker-period-btn active';
            amBtn.setAttribute('data-period', 'AM');
            amBtn.setAttribute('aria-label', 'AM');
            amBtn.setAttribute('aria-pressed', 'true');
            amBtn.textContent = 'AM';
            period.appendChild(amBtn);
            instance.dom.amBtn = amBtn;

            var pmBtn = document.createElement('button');
            pmBtn.type = 'button';
            pmBtn.className = 'rsl-time-picker-period-btn';
            pmBtn.setAttribute('data-period', 'PM');
            pmBtn.setAttribute('aria-label', 'PM');
            pmBtn.setAttribute('aria-pressed', 'false');
            pmBtn.textContent = 'PM';
            period.appendChild(pmBtn);
            instance.dom.pmBtn = pmBtn;

            display.appendChild(period);
            instance.dom.periodContainer = period;

            return display;
        },

        /**
         * Build the clock dial
         */
        _buildClockDial: function(instance) {
            var self = this;
            var config = instance.config;

            var dialContainer = document.createElement('div');
            dialContainer.className = 'rsl-time-picker-dial';
            dialContainer.setAttribute('role', 'group');
            dialContainer.setAttribute('aria-label', 'Clock dial for selecting time');

            // Clock hand
            var hand = document.createElement('div');
            hand.className = 'rsl-time-picker-hand';
            dialContainer.appendChild(hand);
            instance.dom.hand = hand;

            // Center dot
            var center = document.createElement('div');
            center.className = 'rsl-time-picker-dial-center';
            dialContainer.appendChild(center);

            // Numbers container
            var numbersContainer = document.createElement('div');
            numbersContainer.className = 'rsl-time-picker-dial-numbers';
            instance.dom.dialNumbers = numbersContainer;
            dialContainer.appendChild(numbersContainer);

            // Build hour numbers by default
            this._buildDialNumbers(instance, 'hours');

            return dialContainer;
        },

        /**
         * Build dial numbers for hours or minutes
         */
        _buildDialNumbers: function(instance, type) {
            var config = instance.config;
            var container = instance.dom.dialNumbers;
            var is12Hour = config.format === '12';
            var dialSize = 220; // Match CSS variable
            var radius = (dialSize / 2) - 28; // Outer radius for numbers

            // Clear existing
            container.innerHTML = '';

            var numbers = [];
            if (type === 'hours') {
                if (is12Hour) {
                    numbers = [12, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
                } else {
                    numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23];
                }
            } else {
                // Minutes - show based on step
                var step = config.step || 5;
                for (var i = 0; i < 60; i += step) {
                    numbers.push(i);
                }
            }

            var self = this;
            var angleStep = 360 / (type === 'hours' && !is12Hour ? 12 : numbers.length);
            var innerRadius = radius - 34;

            numbers.forEach(function(num, index) {
                var numberEl = document.createElement('button');
                numberEl.type = 'button';
                numberEl.className = 'rsl-time-picker-dial-number';
                numberEl.setAttribute('data-value', num);
                numberEl.setAttribute('data-type', type);
                numberEl.setAttribute('tabindex', '-1');

                var displayNum = type === 'minutes' ? self._padZero(num) : num;
                numberEl.textContent = displayNum;
                numberEl.setAttribute('aria-label', type === 'hours' ? num + ' hours' : num + ' minutes');

                // Calculate position
                var angle, r;
                if (type === 'hours' && !is12Hour) {
                    // 24-hour mode: 0-11 outer, 12-23 inner
                    if (num < 12) {
                        angle = (index * 30) - 90; // 30 degrees per hour, start at top
                        r = radius;
                    } else {
                        angle = ((num - 12) * 30) - 90;
                        r = innerRadius;
                        numberEl.classList.add('inner');
                    }
                } else {
                    angle = (index * angleStep) - 90;
                    r = radius;
                }

                var angleRad = angle * (Math.PI / 180);
                var x = (dialSize / 2) + (r * Math.cos(angleRad)) - 18;
                var y = (dialSize / 2) + (r * Math.sin(angleRad)) - 18;

                numberEl.style.left = x + 'px';
                numberEl.style.top = y + 'px';

                // Check if disabled
                if (type === 'hours') {
                    if (!self._isHourInRange(instance, num)) {
                        numberEl.classList.add('disabled');
                        numberEl.setAttribute('aria-disabled', 'true');
                    }
                } else {
                    var hours = instance.selectedHours !== null ? instance.selectedHours : 0;
                    if (!self._isTimeInRange(instance, hours, num)) {
                        numberEl.classList.add('disabled');
                        numberEl.setAttribute('aria-disabled', 'true');
                    }
                }

                container.appendChild(numberEl);
            });
        },

        /**
         * Build list-based selector (alternative to dial)
         */
        _buildLists: function(instance) {
            var self = this;
            var config = instance.config;
            var is12Hour = config.format === '12';

            var container = document.createElement('div');
            container.className = 'rsl-time-picker-lists';

            // Hours list
            var hoursList = document.createElement('div');
            hoursList.className = 'rsl-time-picker-list';
            hoursList.setAttribute('role', 'listbox');
            hoursList.setAttribute('aria-label', 'Hours');

            var hoursHeader = document.createElement('div');
            hoursHeader.className = 'rsl-time-picker-list-header';
            hoursHeader.textContent = 'Hour';
            hoursHeader.setAttribute('aria-hidden', 'true');
            hoursList.appendChild(hoursHeader);

            var maxHour = is12Hour ? 12 : 23;
            var startHour = is12Hour ? 1 : 0;
            for (var h = startHour; h <= maxHour; h++) {
                var hourItem = document.createElement('div');
                hourItem.className = 'rsl-time-picker-list-item';
                hourItem.setAttribute('role', 'option');
                hourItem.setAttribute('data-value', h);
                hourItem.setAttribute('data-type', 'hours');
                hourItem.setAttribute('tabindex', '-1');
                hourItem.textContent = is12Hour ? h : this._padZero(h);
                hourItem.setAttribute('aria-label', h + ' hours');

                if (!this._isHourInRange(instance, h)) {
                    hourItem.classList.add('disabled');
                    hourItem.setAttribute('aria-disabled', 'true');
                }

                hoursList.appendChild(hourItem);
            }
            container.appendChild(hoursList);
            instance.dom.hoursList = hoursList;

            // Minutes list
            var minutesList = document.createElement('div');
            minutesList.className = 'rsl-time-picker-list';
            minutesList.setAttribute('role', 'listbox');
            minutesList.setAttribute('aria-label', 'Minutes');

            var minutesHeader = document.createElement('div');
            minutesHeader.className = 'rsl-time-picker-list-header';
            minutesHeader.textContent = 'Min';
            minutesHeader.setAttribute('aria-hidden', 'true');
            minutesList.appendChild(minutesHeader);

            var step = config.step || 5;
            for (var m = 0; m < 60; m += step) {
                var minItem = document.createElement('div');
                minItem.className = 'rsl-time-picker-list-item';
                minItem.setAttribute('role', 'option');
                minItem.setAttribute('data-value', m);
                minItem.setAttribute('data-type', 'minutes');
                minItem.setAttribute('tabindex', '-1');
                minItem.textContent = this._padZero(m);
                minItem.setAttribute('aria-label', m + ' minutes');
                minutesList.appendChild(minItem);
            }
            container.appendChild(minutesList);
            instance.dom.minutesList = minutesList;

            // AM/PM list (12-hour only)
            if (is12Hour) {
                var periodList = document.createElement('div');
                periodList.className = 'rsl-time-picker-list';
                periodList.setAttribute('role', 'listbox');
                periodList.setAttribute('aria-label', 'Period');

                var periodHeader = document.createElement('div');
                periodHeader.className = 'rsl-time-picker-list-header';
                periodHeader.textContent = '';
                periodHeader.setAttribute('aria-hidden', 'true');
                periodList.appendChild(periodHeader);

                ['AM', 'PM'].forEach(function(p) {
                    var pItem = document.createElement('div');
                    pItem.className = 'rsl-time-picker-list-item';
                    pItem.setAttribute('role', 'option');
                    pItem.setAttribute('data-value', p);
                    pItem.setAttribute('data-type', 'period');
                    pItem.setAttribute('tabindex', '-1');
                    pItem.textContent = p;
                    pItem.setAttribute('aria-label', p);
                    periodList.appendChild(pItem);
                });
                container.appendChild(periodList);
                instance.dom.periodList = periodList;
            }

            return container;
        },

        /**
         * Build preset buttons
         */
        _buildPresets: function(instance) {
            var self = this;
            var container = document.createElement('div');
            container.className = 'rsl-time-picker-presets';
            container.setAttribute('role', 'group');
            container.setAttribute('aria-label', 'Quick time presets');

            var presetKeys = ['now', 'morning', 'noon', 'afternoon', 'evening'];

            presetKeys.forEach(function(key) {
                var preset = self.presets[key];
                if (!preset) return;

                var btn = document.createElement('button');
                btn.type = 'button';
                btn.className = 'rsl-time-picker-preset';
                btn.setAttribute('data-preset', key);
                btn.textContent = preset.label;
                btn.setAttribute('aria-label', 'Set time to ' + preset.label);
                container.appendChild(btn);
            });

            return container;
        },

        /**
         * Build footer with action buttons
         */
        _buildFooter: function(instance) {
            var footer = document.createElement('div');
            footer.className = 'rsl-time-picker-footer';

            var cancelBtn = document.createElement('button');
            cancelBtn.type = 'button';
            cancelBtn.className = 'rsl-time-picker-btn rsl-time-picker-btn-cancel';
            cancelBtn.textContent = 'Cancel';
            footer.appendChild(cancelBtn);
            instance.dom.cancelBtn = cancelBtn;

            var confirmBtn = document.createElement('button');
            confirmBtn.type = 'button';
            confirmBtn.className = 'rsl-time-picker-btn rsl-time-picker-btn-confirm';
            confirmBtn.textContent = 'OK';
            footer.appendChild(confirmBtn);
            instance.dom.confirmBtn = confirmBtn;

            return footer;
        },

        /**
         * Attach event listeners
         */
        _attachEvents: function(instance) {
            var self = this;
            var config = instance.config;

            // Input click - open picker
            instance.dom.input.addEventListener('click', function() {
                if (!config.disabled && !config.readOnly) {
                    self.open(instance.element);
                }
            });

            // Input keydown
            instance.dom.input.addEventListener('keydown', function(e) {
                self._handleInputKeydown(instance, e);
            });

            // Clear button
            if (instance.dom.clearBtn) {
                instance.dom.clearBtn.addEventListener('click', function(e) {
                    e.stopPropagation();
                    self.clear(instance.element);
                });
            }

            // Range mode: end input
            if (config.mode === 'range' && instance.dom.inputEnd) {
                instance.dom.inputEnd.addEventListener('click', function() {
                    if (!config.disabled && !config.readOnly) {
                        instance.selectingStart = false;
                        self.open(instance.element);
                    }
                });

                instance.dom.inputEnd.addEventListener('keydown', function(e) {
                    self._handleInputKeydown(instance, e);
                });

                if (instance.dom.clearBtnEnd) {
                    instance.dom.clearBtnEnd.addEventListener('click', function(e) {
                        e.stopPropagation();
                        instance.rangeEnd = null;
                        instance.dom.inputEnd.value = '';
                        self._updateHasValueClass(instance);
                        self._emitEvent(instance, 'rsl-time-clear');
                    });
                }
            }

            // Popover events
            this._attachPopoverEvents(instance);

            // Close on outside click
            // Use mousedown instead of click to avoid race condition with dial rebuild
            document.addEventListener('mousedown', function(e) {
                if (instance.isOpen && !instance.dom.wrapper.contains(e.target)) {
                    // Small delay to ensure we're not interfering with popover interactions
                    setTimeout(function() {
                        if (instance.isOpen && !instance.dom.wrapper.contains(document.activeElement)) {
                            self.close(instance.element);
                        }
                    }, 10);
                }
            });

            // Close on Escape
            document.addEventListener('keydown', function(e) {
                if (e.key === 'Escape' && instance.isOpen) {
                    self.close(instance.element);
                    instance.dom.input.focus();
                }
            });
        },

        /**
         * Attach popover event listeners
         */
        _attachPopoverEvents: function(instance) {
            var self = this;
            var config = instance.config;
            var popover = instance.dom.popover;

            // Close button
            if (instance.dom.closeBtn) {
                instance.dom.closeBtn.addEventListener('click', function() {
                    self.close(instance.element);
                });
            }

            // Display segment clicks and focus (hours/minutes)
            // Sync dial mode when clicking OR tabbing to these buttons
            if (instance.dom.hoursDisplay) {
                instance.dom.hoursDisplay.addEventListener('click', function() {
                    self._setActiveSegment(instance, 'hours');
                });
                instance.dom.hoursDisplay.addEventListener('focus', function() {
                    self._setActiveSegment(instance, 'hours');
                });
            }

            if (instance.dom.minutesDisplay) {
                instance.dom.minutesDisplay.addEventListener('click', function() {
                    self._setActiveSegment(instance, 'minutes');
                });
                instance.dom.minutesDisplay.addEventListener('focus', function() {
                    self._setActiveSegment(instance, 'minutes');
                });
            }

            // Period buttons (12-hour mode)
            if (instance.dom.amBtn) {
                instance.dom.amBtn.addEventListener('click', function() {
                    self._setPeriod(instance, 'AM');
                });
            }

            if (instance.dom.pmBtn) {
                instance.dom.pmBtn.addEventListener('click', function() {
                    self._setPeriod(instance, 'PM');
                });
            }

            // Dial number clicks
            if (instance.dom.dialNumbers) {
                instance.dom.dialNumbers.addEventListener('click', function(e) {
                    var numberEl = e.target.closest('.rsl-time-picker-dial-number');
                    if (numberEl && !numberEl.classList.contains('disabled')) {
                        var value = parseInt(numberEl.getAttribute('data-value'), 10);
                        var type = numberEl.getAttribute('data-type');
                        self._selectDialValue(instance, type, value);
                    }
                });
            }

            // List item clicks
            if (instance.dom.hoursList) {
                instance.dom.hoursList.addEventListener('click', function(e) {
                    var item = e.target.closest('.rsl-time-picker-list-item');
                    if (item && !item.classList.contains('disabled')) {
                        var value = parseInt(item.getAttribute('data-value'), 10);
                        self._selectHours(instance, value);
                    }
                });
            }

            if (instance.dom.minutesList) {
                instance.dom.minutesList.addEventListener('click', function(e) {
                    var item = e.target.closest('.rsl-time-picker-list-item');
                    if (item && !item.classList.contains('disabled')) {
                        var value = parseInt(item.getAttribute('data-value'), 10);
                        self._selectMinutes(instance, value);
                    }
                });
            }

            if (instance.dom.periodList) {
                instance.dom.periodList.addEventListener('click', function(e) {
                    var item = e.target.closest('.rsl-time-picker-list-item');
                    if (item) {
                        var value = item.getAttribute('data-value');
                        self._setPeriod(instance, value);
                    }
                });
            }

            // Preset clicks
            if (instance.dom.presets) {
                instance.dom.presets.addEventListener('click', function(e) {
                    var presetBtn = e.target.closest('.rsl-time-picker-preset');
                    if (presetBtn) {
                        var presetKey = presetBtn.getAttribute('data-preset');
                        self._applyPreset(instance, presetKey);
                    }
                });
            }

            // Footer buttons
            if (instance.dom.cancelBtn) {
                instance.dom.cancelBtn.addEventListener('click', function() {
                    self.close(instance.element);
                });
            }

            if (instance.dom.confirmBtn) {
                instance.dom.confirmBtn.addEventListener('click', function() {
                    self._confirmSelection(instance);
                });
            }

            // Keyboard navigation in popover
            popover.addEventListener('keydown', function(e) {
                self._handlePopoverKeydown(instance, e);
            });
        },

        /**
         * Handle input keydown
         */
        _handleInputKeydown: function(instance, e) {
            var config = instance.config;

            switch (e.key) {
                case 'Enter':
                case ' ':
                    e.preventDefault();
                    if (!instance.isOpen) {
                        this.open(instance.element);
                    }
                    break;
                case 'ArrowDown':
                    e.preventDefault();
                    if (!instance.isOpen) {
                        this.open(instance.element);
                    }
                    break;
                case 'Delete':
                case 'Backspace':
                    if (config.clearable && instance.dom.input.value) {
                        e.preventDefault();
                        this.clear(instance.element);
                    }
                    break;
            }
        },

        /**
         * Handle popover keydown
         */
        _handlePopoverKeydown: function(instance, e) {
            var self = this;
            var target = document.activeElement;

            // Check if focus is on AM/PM buttons
            var isOnPeriodButton = target && (
                target.classList.contains('rsl-time-picker-period-btn') ||
                (target.closest && target.closest('.rsl-time-picker-period'))
            );

            // Check if focus is on hours or minutes display
            var isOnHoursMinutes = target && (
                target.classList.contains('rsl-time-picker-display-segment')
            );

            switch (e.key) {
                case 'ArrowUp':
                case 'ArrowDown':
                    e.preventDefault();
                    if (isOnPeriodButton) {
                        // Toggle between AM and PM
                        var newPeriod = instance.selectedPeriod === 'AM' ? 'PM' : 'AM';
                        this._setPeriod(instance, newPeriod);
                        // Keep focus on the appropriate button
                        if (newPeriod === 'AM' && instance.dom.amBtn) {
                            instance.dom.amBtn.focus();
                        } else if (newPeriod === 'PM' && instance.dom.pmBtn) {
                            instance.dom.pmBtn.focus();
                        }
                    } else if (isOnHoursMinutes) {
                        // Only change time when on hours/minutes
                        var direction = e.key === 'ArrowUp' ? 1 : -1;
                        this._incrementSegment(instance, direction);
                    }
                    // If on other elements (presets, close, etc.), do nothing
                    break;
                case 'ArrowLeft':
                    e.preventDefault();
                    this._moveToPreviousSegment(instance);
                    break;
                case 'ArrowRight':
                    e.preventDefault();
                    this._moveToNextSegment(instance);
                    break;
                case 'Tab':
                    // Let tab work naturally but trap within popover
                    this._handleTabKey(instance, e);
                    break;
                case 'Enter':
                case ' ':
                    // Don't intercept Enter/Space on interactive elements (buttons, etc.)
                    // Let them trigger their own click handlers
                    var target = document.activeElement;
                    var isInteractiveElement = target && (
                        target.tagName === 'BUTTON' ||
                        target.classList.contains('rsl-time-picker-period-btn') ||
                        target.classList.contains('rsl-time-picker-preset') ||
                        target.classList.contains('rsl-time-picker-list-item') ||
                        target.classList.contains('rsl-time-picker-dial-number') ||
                        target.classList.contains('rsl-time-picker-close')
                    );

                    if (!isInteractiveElement) {
                        e.preventDefault();
                        if (instance.config.autoApply) {
                            this._confirmSelection(instance);
                        }
                    }
                    // If on an interactive element, let the native click happen
                    break;
                case 'Home':
                    e.preventDefault();
                    this._jumpToMinTime(instance);
                    break;
                case 'End':
                    e.preventDefault();
                    this._jumpToMaxTime(instance);
                    break;
            }
        },

        /**
         * Handle Tab key for focus trap
         */
        _handleTabKey: function(instance, e) {
            var popover = instance.dom.popover;
            var focusable = popover.querySelectorAll(
                'button:not([disabled]):not([tabindex="-1"]), [tabindex="0"]'
            );

            if (focusable.length === 0) return;

            var first = focusable[0];
            var last = focusable[focusable.length - 1];

            if (e.shiftKey && document.activeElement === first) {
                e.preventDefault();
                last.focus();
            } else if (!e.shiftKey && document.activeElement === last) {
                e.preventDefault();
                first.focus();
            }
        },

        /**
         * Set active segment (hours, minutes, period)
         */
        _setActiveSegment: function(instance, segment) {
            instance.activeSegment = segment;

            // Update display UI
            if (instance.dom.hoursDisplay) {
                instance.dom.hoursDisplay.classList.toggle('active', segment === 'hours');
            }
            if (instance.dom.minutesDisplay) {
                instance.dom.minutesDisplay.classList.toggle('active', segment === 'minutes');
            }

            // Update dial if present
            if (instance.dom.dial) {
                this._buildDialNumbers(instance, segment);
                this._updateHandPosition(instance);
            }

            // Announce to screen reader
            this._announce(instance, 'Now selecting ' + segment);
        },

        /**
         * Move to previous segment
         */
        _moveToPreviousSegment: function(instance) {
            var is12Hour = instance.config.format === '12';
            if (instance.activeSegment === 'minutes') {
                this._setActiveSegment(instance, 'hours');
            } else if (instance.activeSegment === 'period' && is12Hour) {
                this._setActiveSegment(instance, 'minutes');
            }
        },

        /**
         * Move to next segment
         */
        _moveToNextSegment: function(instance) {
            var is12Hour = instance.config.format === '12';
            if (instance.activeSegment === 'hours') {
                this._setActiveSegment(instance, 'minutes');
            } else if (instance.activeSegment === 'minutes' && is12Hour) {
                // Focus period buttons
                if (instance.dom.amBtn) {
                    instance.dom.amBtn.focus();
                }
            }
        },

        /**
         * Increment current segment value
         */
        _incrementSegment: function(instance, direction) {
            var config = instance.config;
            var is12Hour = config.format === '12';

            if (instance.activeSegment === 'hours') {
                var currentHour = instance.selectedHours !== null ? instance.selectedHours : 0;
                var maxHour = is12Hour ? 12 : 23;
                var minHour = is12Hour ? 1 : 0;
                var newHour = currentHour + direction;

                if (newHour > maxHour) newHour = minHour;
                if (newHour < minHour) newHour = maxHour;

                this._selectHours(instance, newHour);
            } else if (instance.activeSegment === 'minutes') {
                var currentMin = instance.selectedMinutes !== null ? instance.selectedMinutes : 0;
                var step = config.step || 5;
                var newMin = currentMin + (direction * step);

                if (newMin >= 60) newMin = 0;
                if (newMin < 0) newMin = 60 - step;

                this._selectMinutes(instance, newMin);
            }
        },

        /**
         * Jump to minimum time
         */
        _jumpToMinTime: function(instance) {
            var config = instance.config;
            if (config.minTime) {
                var parts = config.minTime.split(':');
                this._selectHours(instance, parseInt(parts[0], 10));
                this._selectMinutes(instance, parseInt(parts[1], 10));
            } else {
                this._selectHours(instance, config.format === '12' ? 1 : 0);
                this._selectMinutes(instance, 0);
            }
        },

        /**
         * Jump to maximum time
         */
        _jumpToMaxTime: function(instance) {
            var config = instance.config;
            if (config.maxTime) {
                var parts = config.maxTime.split(':');
                this._selectHours(instance, parseInt(parts[0], 10));
                this._selectMinutes(instance, parseInt(parts[1], 10));
            } else {
                this._selectHours(instance, config.format === '12' ? 12 : 23);
                this._selectMinutes(instance, 59);
            }
        },

        /**
         * Select value from dial
         */
        _selectDialValue: function(instance, type, value) {
            if (type === 'hours') {
                this._selectHours(instance, value);
                // Auto-advance to minutes
                this._setActiveSegment(instance, 'minutes');
            } else {
                this._selectMinutes(instance, value);
                // If auto-apply, confirm
                if (instance.config.autoApply && instance.config.closeOnSelect) {
                    this._confirmSelection(instance);
                }
            }
        },

        /**
         * Select hours
         */
        _selectHours: function(instance, hours) {
            instance.selectedHours = hours;
            this._updateDisplay(instance);
            this._updateSelection(instance, 'hours', hours);
            this._updateHandPosition(instance);
            this._announce(instance, hours + ' hours selected');

            // In 24-hour mode, show AM/PM selector for ambiguous hours (1-11)
            if (instance.config.format === '24' && instance.dom.periodContainer) {
                var isAmbiguous = hours >= 1 && hours <= 11;
                instance.dom.periodContainer.style.display = isAmbiguous ? '' : 'none';

                if (isAmbiguous) {
                    // Reset to AM when showing the period selector
                    this._setPeriod(instance, 'AM');
                    this._announce(instance, 'Select AM or PM to clarify');
                }
            }

            if (instance.config.autoApply) {
                this._applySelection(instance);
            }
        },

        /**
         * Select minutes
         */
        _selectMinutes: function(instance, minutes) {
            instance.selectedMinutes = minutes;
            this._updateDisplay(instance);
            this._updateSelection(instance, 'minutes', minutes);
            this._updateHandPosition(instance);
            this._announce(instance, minutes + ' minutes selected');

            if (instance.config.autoApply) {
                this._applySelection(instance);
            }
        },

        /**
         * Set period (AM/PM)
         */
        _setPeriod: function(instance, period) {
            var oldPeriod = instance.selectedPeriod;
            instance.selectedPeriod = period;

            // In 24-hour mode with ambiguous hours, convert hour when period changes
            if (instance.config.format === '24' && instance.selectedHours !== null) {
                var hours = instance.selectedHours;
                // Only convert if hour is in the ambiguous range (1-11 or was converted to 13-23)
                if (hours >= 1 && hours <= 11 && period === 'PM') {
                    // Convert AM to PM: add 12
                    instance.selectedHours = hours + 12;
                    this._updateDisplay(instance);
                    this._updateSelection(instance, 'hours', instance.selectedHours);
                    this._updateHandPosition(instance);
                } else if (hours >= 13 && hours <= 23 && period === 'AM') {
                    // Convert PM back to AM: subtract 12
                    instance.selectedHours = hours - 12;
                    this._updateDisplay(instance);
                    this._updateSelection(instance, 'hours', instance.selectedHours);
                    this._updateHandPosition(instance);
                }
            }

            // Update buttons
            if (instance.dom.amBtn) {
                instance.dom.amBtn.classList.toggle('active', period === 'AM');
                instance.dom.amBtn.setAttribute('aria-pressed', period === 'AM' ? 'true' : 'false');
            }
            if (instance.dom.pmBtn) {
                instance.dom.pmBtn.classList.toggle('active', period === 'PM');
                instance.dom.pmBtn.setAttribute('aria-pressed', period === 'PM' ? 'true' : 'false');
            }

            // Update list selection
            if (instance.dom.periodList) {
                var items = instance.dom.periodList.querySelectorAll('.rsl-time-picker-list-item');
                items.forEach(function(item) {
                    item.classList.toggle('selected', item.getAttribute('data-value') === period);
                    item.setAttribute('aria-selected', item.getAttribute('data-value') === period ? 'true' : 'false');
                });
            }

            this._announce(instance, period + ' selected');

            if (instance.config.autoApply) {
                this._applySelection(instance);
            }
        },

        /**
         * Apply preset
         */
        _applyPreset: function(instance, presetKey) {
            var preset = this.presets[presetKey];
            if (!preset) return;

            var time = preset.getTime();
            var config = instance.config;
            var is12Hour = config.format === '12';

            var hours = time.hours;
            var period = 'AM';

            if (is12Hour) {
                if (hours === 0) {
                    hours = 12;
                    period = 'AM';
                } else if (hours === 12) {
                    period = 'PM';
                } else if (hours > 12) {
                    hours = hours - 12;
                    period = 'PM';
                }
            }

            this._selectHours(instance, hours);
            this._selectMinutes(instance, time.minutes);
            if (is12Hour) {
                this._setPeriod(instance, period);
            }

            // Update preset button states
            var presetBtns = instance.dom.presets.querySelectorAll('.rsl-time-picker-preset');
            presetBtns.forEach(function(btn) {
                btn.classList.toggle('active', btn.getAttribute('data-preset') === presetKey);
            });

            this._announce(instance, preset.label + ' selected, ' + this._formatTime(instance));

            if (config.closeOnSelect) {
                this._confirmSelection(instance);
            }
        },

        /**
         * Update the display (hours:minutes in header)
         */
        _updateDisplay: function(instance) {
            var hours = instance.selectedHours;
            var minutes = instance.selectedMinutes;

            if (instance.dom.hoursDisplay) {
                instance.dom.hoursDisplay.textContent = hours !== null ? (instance.config.format === '12' ? hours : this._padZero(hours)) : '--';
            }
            if (instance.dom.minutesDisplay) {
                instance.dom.minutesDisplay.textContent = minutes !== null ? this._padZero(minutes) : '--';
            }
        },

        /**
         * Update selection state in dial or list
         */
        _updateSelection: function(instance, type, value) {
            // Update dial
            if (instance.dom.dialNumbers) {
                var numbers = instance.dom.dialNumbers.querySelectorAll('.rsl-time-picker-dial-number');
                numbers.forEach(function(num) {
                    num.classList.toggle('selected', parseInt(num.getAttribute('data-value'), 10) === value);
                });
            }

            // Update list
            var list = type === 'hours' ? instance.dom.hoursList : instance.dom.minutesList;
            if (list) {
                var items = list.querySelectorAll('.rsl-time-picker-list-item');
                items.forEach(function(item) {
                    var isSelected = parseInt(item.getAttribute('data-value'), 10) === value;
                    item.classList.toggle('selected', isSelected);
                    item.setAttribute('aria-selected', isSelected ? 'true' : 'false');
                });

                // Scroll selected into view
                var selected = list.querySelector('.rsl-time-picker-list-item.selected');
                if (selected) {
                    selected.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
                }
            }
        },

        /**
         * Update clock hand position
         */
        _updateHandPosition: function(instance) {
            if (!instance.dom.hand) return;

            var value, angle;
            if (instance.activeSegment === 'hours') {
                value = instance.selectedHours !== null ? instance.selectedHours : 0;
                var is12Hour = instance.config.format === '12';
                if (is12Hour) {
                    angle = (value % 12) * 30; // 30 degrees per hour
                } else {
                    angle = (value % 12) * 30;
                }
            } else {
                value = instance.selectedMinutes !== null ? instance.selectedMinutes : 0;
                angle = value * 6; // 6 degrees per minute
            }

            instance.dom.hand.style.transform = 'translateX(-50%) rotate(' + angle + 'deg)';
        },

        /**
         * Apply selection (update input value)
         */
        _applySelection: function(instance) {
            var formatted = this._formatTime(instance);
            var value24 = this._get24HourValue(instance);

            if (instance.config.mode === 'range') {
                if (instance.selectingStart) {
                    instance.rangeStart = value24;
                    instance.dom.input.value = formatted;
                } else {
                    instance.rangeEnd = value24;
                    instance.dom.inputEnd.value = formatted;
                }
            } else {
                instance.dom.input.value = formatted;
            }

            this._updateHasValueClass(instance);

            // Update original input if present
            if (instance.dom.originalInput) {
                instance.dom.originalInput.value = value24;
            }

            // Emit change event on every selection (for real-time updates with autoApply)
            if (instance.config.autoApply) {
                this._emitEvent(instance, 'rsl-time-change', {
                    time: value24,
                    formatted: formatted,
                    hours: instance.selectedHours,
                    minutes: instance.selectedMinutes,
                    period: instance.selectedPeriod
                });
            }

            // Publish to FilterBus on every selection change (for real-time filtering)
            this._publishToFilterBus(instance, value24);
        },

        /**
         * Confirm selection and close
         */
        _confirmSelection: function(instance) {
            if (instance.selectedHours === null) {
                this._announce(instance, 'Please select a time');
                return;
            }

            this._applySelection(instance);

            // Only emit event here if autoApply is false (otherwise _applySelection already emits)
            if (!instance.config.autoApply) {
                var value24 = this._get24HourValue(instance);
                var formatted = this._formatTime(instance);

                // Emit event
                this._emitEvent(instance, 'rsl-time-change', {
                    time: value24,
                    formatted: formatted,
                    hours: instance.selectedHours,
                    minutes: instance.selectedMinutes,
                    period: instance.selectedPeriod
                });

                // Publish to FilterBus if configured
                this._publishToFilterBus(instance, value24);
            }

            this.close(instance.element);
            instance.dom.input.focus();
        },

        /**
         * Open the picker
         */
        open: function(element) {
            var instance = this.instances.get(element);
            if (!instance || instance.isOpen) return;

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

            // Position popover
            this._positionPopover(instance);

            // Focus first interactive element after a brief delay to ensure DOM is ready
            var self = this;
            setTimeout(function() {
                if (instance.dom.hoursDisplay) {
                    instance.dom.hoursDisplay.focus();
                    self._setActiveSegment(instance, 'hours');
                }
            }, 50);

            this._emitEvent(instance, 'rsl-time-open');
            this._announce(instance, 'Time picker opened. Use arrow keys to select time.');
        },

        /**
         * Close the picker
         */
        close: function(element) {
            var instance = this.instances.get(element);
            if (!instance || !instance.isOpen) return;

            instance.isOpen = false;
            instance.dom.wrapper.classList.remove('open');
            instance.dom.popover.classList.remove('open');
            instance.dom.input.setAttribute('aria-expanded', 'false');

            this._emitEvent(instance, 'rsl-time-close');
        },

        /**
         * Clear the value
         */
        clear: function(element) {
            var instance = this.instances.get(element);
            if (!instance) return;

            instance.selectedHours = null;
            instance.selectedMinutes = null;
            instance.selectedPeriod = 'AM';
            instance.dom.input.value = '';

            if (instance.config.mode === 'range') {
                instance.rangeStart = null;
                instance.rangeEnd = null;
                if (instance.dom.inputEnd) {
                    instance.dom.inputEnd.value = '';
                }
            }

            this._updateDisplay(instance);
            this._updateHasValueClass(instance);

            if (instance.dom.originalInput) {
                instance.dom.originalInput.value = '';
            }

            this._emitEvent(instance, 'rsl-time-clear');
            this._publishToFilterBus(instance, null);
            this._announce(instance, 'Time cleared');
        },

        /**
         * Get the current value
         */
        getValue: function(element) {
            var instance = this.instances.get(element);
            if (!instance) return null;

            if (instance.config.mode === 'range') {
                return {
                    start: instance.rangeStart,
                    end: instance.rangeEnd
                };
            }

            return this._get24HourValue(instance);
        },

        /**
         * Set the value programmatically
         */
        setValue: function(element, value) {
            var instance = this.instances.get(element);
            if (!instance) return;

            if (typeof value === 'string') {
                this._setInitialValue(instance, value);
            } else if (value && typeof value === 'object') {
                if (value.start) this._setInitialValue(instance, value.start, 'start');
                if (value.end) this._setInitialValue(instance, value.end, 'end');
            }
        },

        /**
         * Destroy instance
         */
        destroy: function(element) {
            var instance = this.instances.get(element);
            if (!instance) return;

            // Remove wrapper
            if (instance.dom.wrapper && instance.dom.wrapper.parentNode) {
                // Restore original input if present
                if (instance.dom.originalInput) {
                    instance.dom.originalInput.style.display = '';
                    instance.dom.wrapper.parentNode.insertBefore(instance.dom.originalInput, instance.dom.wrapper);
                }
                instance.dom.wrapper.parentNode.removeChild(instance.dom.wrapper);
            }

            this.instances.delete(element);
        },

        // ==========================================
        // Helper Methods
        // ==========================================

        /**
         * Set initial value from string
         */
        _setInitialValue: function(instance, value, target) {
            if (!value) return;

            var config = instance.config;

            // Handle 'now' keyword
            if (value === 'now') {
                var now = new Date();
                instance.selectedHours = now.getHours();
                instance.selectedMinutes = now.getMinutes();
            } else {
                // Parse time string
                var parsed = this._parseTimeString(value, config.format);
                if (parsed) {
                    instance.selectedHours = parsed.hours;
                    instance.selectedMinutes = parsed.minutes;
                    if (config.format === '12') {
                        instance.selectedPeriod = parsed.period;
                    }
                }
            }

            // Convert to 12-hour format for display if needed
            if (config.format === '12' && instance.selectedHours !== null) {
                var hours24 = instance.selectedHours;
                if (hours24 === 0) {
                    instance.selectedHours = 12;
                    instance.selectedPeriod = 'AM';
                } else if (hours24 === 12) {
                    instance.selectedPeriod = 'PM';
                } else if (hours24 > 12) {
                    instance.selectedHours = hours24 - 12;
                    instance.selectedPeriod = 'PM';
                } else {
                    instance.selectedPeriod = 'AM';
                }
            }

            this._updateDisplay(instance);
            this._applySelection(instance);

            if (config.format === '12') {
                this._setPeriod(instance, instance.selectedPeriod);
            }
        },

        /**
         * Parse time string to hours/minutes
         */
        _parseTimeString: function(str, format) {
            if (!str) return null;

            str = str.trim().toUpperCase();

            // Try various formats
            var matches;

            // HH:mm AM/PM
            matches = str.match(/^(\d{1,2}):(\d{2})\s*(AM|PM)?$/i);
            if (matches) {
                var hours = parseInt(matches[1], 10);
                var minutes = parseInt(matches[2], 10);
                var period = matches[3] || (hours >= 12 ? 'PM' : 'AM');

                // Convert to 24-hour if AM/PM provided
                if (period === 'PM' && hours < 12) hours += 12;
                if (period === 'AM' && hours === 12) hours = 0;

                return { hours: hours, minutes: minutes, period: period };
            }

            // Just hours (e.g., "9" or "9am")
            matches = str.match(/^(\d{1,2})\s*(AM|PM)?$/i);
            if (matches) {
                var h = parseInt(matches[1], 10);
                var p = matches[2] || (h >= 12 ? 'PM' : 'AM');
                if (p === 'PM' && h < 12) h += 12;
                if (p === 'AM' && h === 12) h = 0;
                return { hours: h, minutes: 0, period: p };
            }

            return null;
        },

        /**
         * Format time for display
         */
        _formatTime: function(instance) {
            var config = instance.config;
            var hours = instance.selectedHours;
            var minutes = instance.selectedMinutes;

            if (hours === null) return '';

            var formatted;
            if (config.format === '12') {
                formatted = hours + ':' + this._padZero(minutes !== null ? minutes : 0) + ' ' + instance.selectedPeriod;
            } else {
                formatted = this._padZero(hours) + ':' + this._padZero(minutes !== null ? minutes : 0);
            }

            return formatted;
        },

        /**
         * Get 24-hour format value (HH:mm)
         */
        _get24HourValue: function(instance) {
            var hours = instance.selectedHours;
            var minutes = instance.selectedMinutes;

            if (hours === null) return null;

            // Convert to 24-hour if in 12-hour mode
            if (instance.config.format === '12') {
                if (instance.selectedPeriod === 'PM' && hours < 12) {
                    hours += 12;
                } else if (instance.selectedPeriod === 'AM' && hours === 12) {
                    hours = 0;
                }
            }

            return this._padZero(hours) + ':' + this._padZero(minutes !== null ? minutes : 0);
        },

        /**
         * Check if hour is within range
         */
        _isHourInRange: function(instance, hour) {
            var config = instance.config;
            if (!config.minTime && !config.maxTime) return true;

            // Convert to 24-hour for comparison
            var hour24 = hour;
            if (config.format === '12') {
                if (instance.selectedPeriod === 'PM' && hour < 12) hour24 += 12;
                if (instance.selectedPeriod === 'AM' && hour === 12) hour24 = 0;
            }

            if (config.minTime) {
                var minHour = parseInt(config.minTime.split(':')[0], 10);
                if (hour24 < minHour) return false;
            }

            if (config.maxTime) {
                var maxHour = parseInt(config.maxTime.split(':')[0], 10);
                if (hour24 > maxHour) return false;
            }

            return true;
        },

        /**
         * Check if time is within range
         */
        _isTimeInRange: function(instance, hours, minutes) {
            var config = instance.config;
            if (!config.minTime && !config.maxTime) return true;

            var timeValue = hours * 60 + minutes;

            if (config.minTime) {
                var minParts = config.minTime.split(':');
                var minValue = parseInt(minParts[0], 10) * 60 + parseInt(minParts[1], 10);
                if (timeValue < minValue) return false;
            }

            if (config.maxTime) {
                var maxParts = config.maxTime.split(':');
                var maxValue = parseInt(maxParts[0], 10) * 60 + parseInt(maxParts[1], 10);
                if (timeValue > maxValue) return false;
            }

            return true;
        },

        /**
         * Position popover to avoid viewport overflow
         */
        _positionPopover: function(instance) {
            var popover = instance.dom.popover;
            var wrapper = instance.dom.wrapper;
            var input = instance.dom.input;
            var rect = wrapper.getBoundingClientRect();
            var popoverHeight = popover.offsetHeight || 400;
            var popoverWidth = popover.offsetWidth || 320;

            // Reset position classes and inline styles
            popover.classList.remove('position-top', 'position-left');
            popover.style.left = '';
            popover.style.right = '';

            // Check if there's room below
            if (rect.bottom + popoverHeight > window.innerHeight) {
                // Position above
                popover.classList.add('position-top');
            }

            // Check if there's room to the right
            var rightEdge = rect.left + popoverWidth;
            var viewportWidth = window.innerWidth;
            var padding = 16; // Minimum padding from viewport edge

            if (rightEdge > viewportWidth - padding) {
                // Popover would overflow right edge - shift it left
                var overflow = rightEdge - (viewportWidth - padding);

                // Check if we can align to the right edge of the input instead
                var rightAlignedLeft = rect.right - popoverWidth;

                if (rightAlignedLeft >= padding) {
                    // Align popover's right edge with input's right edge
                    popover.style.left = 'auto';
                    popover.style.right = '0';
                    popover.classList.add('position-left');
                } else {
                    // Just shift left by the overflow amount
                    popover.style.left = (-overflow) + 'px';
                }
            }
        },

        /**
         * Update has-value class for styling
         */
        _updateHasValueClass: function(instance) {
            var hasValue = instance.dom.input.value !== '';
            instance.dom.wrapper.classList.toggle('has-value', hasValue);
        },

        /**
         * Set disabled state
         */
        _setDisabled: function(instance, disabled) {
            instance.config.disabled = disabled;
            instance.dom.input.disabled = disabled;
            if (instance.dom.inputEnd) {
                instance.dom.inputEnd.disabled = disabled;
            }
        },

        /**
         * Set readonly state
         */
        _setReadOnly: function(instance, readOnly) {
            instance.config.readOnly = readOnly;
            instance.dom.input.readOnly = readOnly;
            if (instance.dom.inputEnd) {
                instance.dom.inputEnd.readOnly = readOnly;
            }
        },

        /**
         * Announce to screen readers
         */
        _announce: function(instance, message) {
            if (instance.dom.liveRegion) {
                instance.dom.liveRegion.textContent = message;
            }
        },

        /**
         * Emit custom event
         */
        _emitEvent: function(instance, eventName, detail) {
            var event = new CustomEvent(eventName, {
                bubbles: true,
                detail: detail || {}
            });
            instance.element.dispatchEvent(event);
        },

        /**
         * Publish to FilterBus
         */
        _publishToFilterBus: function(instance, value) {
            var config = instance.config;
            if (!config.filterBusKey) return;

            if (window.RSL && window.RSL.FilterBus) {
                window.RSL.FilterBus.publish(config.filterBusKey, {
                    time: value,
                    formatted: this._formatTime(instance),
                    mode: config.mode
                });
            }
        },

        /**
         * Pad number with leading zero
         */
        _padZero: function(n) {
            return n < 10 ? '0' + n : String(n);
        },

        /**
         * Generate unique ID
         */
        _generateId: function() {
            return Math.random().toString(36).substr(2, 9);
        }
    };

    // Auto-initialize on DOMContentLoaded
    document.addEventListener('DOMContentLoaded', function() {
        window.RSL.TimePicker.init();
    });

})();
