/**
 * RUHONDO BEACH RESORT HMS + POS System
 * AJAX Handlers and Dynamic Content Loader
 * Developer: JOACHIM'S INNOTECH
 * Version: 1.0.0
 */

// =============================================
// AJAX LOADER MODULE
// =============================================
const AjaxLoader = {
    // Cache for loaded content
    cache: new Map(),
    
    // Active requests
    activeRequests: new Set(),
    
    /**
     * Initialize AJAX loader
     */
    init: function() {
        this.setupGlobalHandlers();
        this.initInfiniteScroll();
        this.initLazyLoad();
        this.initAutoRefresh();
    },
    
    /**
     * Setup global AJAX handlers
     */
    setupGlobalHandlers: function() {
        // Setup AJAX for all data-ajax links
        $(document).on('click', '[data-ajax]', (e) => {
            e.preventDefault();
            const $el = $(e.currentTarget);
            this.loadUrl($el.attr('href'), {
                target: $el.data('target'),
                method: $el.data('method') || 'GET',
                data: $el.data('params'),
                replace: $el.data('replace') || false,
                callback: $el.data('callback')
            });
        });
        
        // Setup AJAX forms
        $(document).on('submit', '[data-ajax-form]', (e) => {
            e.preventDefault();
            this.submitForm(e.target);
        });
        
        // Setup AJAX filters
        $(document).on('change', '[data-ajax-filter]', this.debounce(function() {
            this.applyFilters();
        }, 500));
        
        // Setup AJAX pagination
        $(document).on('click', '[data-ajax-pagination] a', (e) => {
            e.preventDefault();
            this.loadPage($(e.currentTarget).attr('href'));
        });
    },
    
    // =========================================
    // CONTENT LOADING
    // =========================================
    
    /**
     * Load URL via AJAX
     */
    loadUrl: function(url, options = {}) {
        const defaults = {
            target: '#content-area',
            method: 'GET',
            data: null,
            replace: false,
            callback: null,
            useCache: false,
            showLoading: true,
            cacheKey: url
        };
        
        const settings = {...defaults, ...options};
        
        // Check cache
        if (settings.useCache && this.cache.has(settings.cacheKey)) {
            this.updateTarget(settings.target, this.cache.get(settings.cacheKey), settings);
            return;
        }
        
        // Show loading
        if (settings.showLoading) {
            this.showLoading(settings.target);
        }
        
        // Create abort controller for this request
        const controller = new AbortController();
        const requestId = Symbol();
        this.activeRequests.add(requestId);
        
        // Prepare request data
        let requestData = settings.data;
        if (settings.method === 'POST' && typeof requestData === 'object') {
            requestData.csrf_token = App.config.csrfToken;
        }
        
        // Make AJAX request
        $.ajax({
            url: url,
            method: settings.method,
            data: requestData,
            dataType: 'json',
            headers: {
                'X-CSRF-Token': App.config.csrfToken,
                'X-Requested-With': 'XMLHttpRequest'
            },
            success: (response) => {
                if (response.status === 'success' && response.data) {
                    // Cache response
                    if (settings.useCache) {
                        this.cache.set(settings.cacheKey, response.data);
                    }
                    
                    // Update target
                    this.updateTarget(settings.target, response.data, settings);
                    
                    // Execute callback
                    if (settings.callback && typeof window[settings.callback] === 'function') {
                        window[settings.callback](response.data);
                    }
                    
                    // Trigger event
                    $(document).trigger('ajax:loaded', [url, response.data]);
                } else {
                    this.showError(settings.target, response.message || 'Failed to load content');
                }
            },
            error: (xhr, status, error) => {
                if (status !== 'abort') {
                    this.showError(settings.target, 'An error occurred while loading content');
                    console.error('AJAX error:', error);
                }
            },
            complete: () => {
                this.activeRequests.delete(requestId);
                if (settings.showLoading) {
                    this.hideLoading(settings.target);
                }
            }
        });
        
        return controller;
    },
    
    /**
     * Update target with loaded content
     */
    updateTarget: function(target, data, settings) {
        const $target = $(target);
        
        if (settings.replace) {
            $target.replaceWith(data);
        } else {
            $target.html(data);
        }
        
        // Reinitialize components for new content
        this.reinitializeComponents(target);
    },
    
    /**
     * Load page via AJAX (for pagination)
     */
    loadPage: function(url) {
        this.loadUrl(url, {
            target: '[data-ajax-container]',
            callback: 'initComponents'
        });
        
        // Update URL without reload
        history.pushState({}, '', url);
    },
    
    /**
     * Apply filters from filter form
     */
    applyFilters: function() {
        const $filters = $('[data-ajax-filter]');
        const data = {};
        
        $filters.each(function() {
            const $el = $(this);
            data[$el.attr('name')] = $el.val();
        });
        
        this.loadUrl(window.location.pathname, {
            method: 'GET',
            data: data,
            target: '[data-ajax-container]',
            replace: true
        });
    },
    
    // =========================================
    // FORM SUBMISSION
    // =========================================
    
    /**
     * Submit form via AJAX
     */
    submitForm: function(form) {
        const $form = $(form);
        const url = $form.attr('action');
        const method = $form.attr('method') || 'POST';
        const target = $form.data('ajax-target') || '#message-area';
        const formData = new FormData(form);
        
        // Add CSRF token
        formData.append(App.config.csrfParam, App.config.csrfToken);
        
        // Show loading
        this.showLoading(target);
        
        // Submit
        $.ajax({
            url: url,
            method: method,
            data: formData,
            processData: false,
            contentType: false,
            dataType: 'json',
            success: (response) => {
                if (response.status === 'success') {
                    // Show success message
                    $(target).html(this.formatMessage('success', response.message || 'Operation completed successfully'));
                    
                    // Clear form if specified
                    if ($form.data('ajax-clear')) {
                        $form[0].reset();
                    }
                    
                    // Reload container if specified
                    if ($form.data('ajax-reload')) {
                        this.reloadContainer($form.data('ajax-reload'));
                    }
                    
                    // Close modal if specified
                    if ($form.data('ajax-close-modal')) {
                        $($form.data('ajax-close-modal')).modal('hide');
                    }
                    
                    // Trigger form success event
                    $form.trigger('ajax:success', [response]);
                } else {
                    // Show validation errors
                    if (response.errors) {
                        this.showValidationErrors($form, response.errors);
                    } else {
                        $(target).html(this.formatMessage('error', response.message || 'An error occurred'));
                    }
                }
            },
            error: (xhr) => {
                const response = xhr.responseJSON;
                $(target).html(this.formatMessage('error', response?.message || 'An error occurred'));
            },
            complete: () => {
                this.hideLoading(target);
            }
        });
    },
    
    /**
     * Show validation errors on form
     */
    showValidationErrors: function($form, errors) {
        // Clear existing errors
        $form.find('.is-invalid').removeClass('is-invalid');
        $form.find('.invalid-feedback').remove();
        
        // Show new errors
        $.each(errors, (field, messages) => {
            const $input = $form.find(`[name="${field}"]`);
            if ($input.length) {
                $input.addClass('is-invalid');
                
                if (Array.isArray(messages)) {
                    messages.forEach(message => {
                        $input.after(`<div class="invalid-feedback">${message}</div>`);
                    });
                } else {
                    $input.after(`<div class="invalid-feedback">${messages}</div>`);
                }
            }
        });
    },
    
    // =========================================
    // INFINITE SCROLL
    // =========================================
    
    /**
     * Initialize infinite scroll
     */
    initInfiniteScroll: function() {
        const $scrollContainer = $('[data-infinite-scroll]');
        if (!$scrollContainer.length) return;
        
        let currentPage = 1;
        let loading = false;
        let hasMore = true;
        
        const loadMore = () => {
            if (loading || !hasMore) return;
            
            loading = true;
            currentPage++;
            
            $.ajax({
                url: window.location.pathname,
                data: {
                    page: currentPage,
                    infinite: true
                },
                success: (response) => {
                    if (response.data && response.data.length > 0) {
                        $scrollContainer.append(response.data);
                        hasMore = response.has_more;
                    } else {
                        hasMore = false;
                    }
                },
                complete: () => {
                    loading = false;
                }
            });
        };
        
        // Check scroll position
        $(window).scroll(this.throttle(() => {
            const scrollPosition = $(window).scrollTop() + $(window).height();
            const triggerPosition = $(document).height() - 200;
            
            if (scrollPosition > triggerPosition) {
                loadMore();
            }
        }, 250));
    },
    
    // =========================================
    // LAZY LOAD
    // =========================================
    
    /**
     * Initialize lazy loading
     */
    initLazyLoad: function() {
        if ('IntersectionObserver' in window) {
            const imageObserver = new IntersectionObserver((entries) => {
                entries.forEach(entry => {
                    if (entry.isIntersecting) {
                        const img = entry.target;
                        img.src = img.dataset.src;
                        if (img.dataset.srcset) {
                            img.srcset = img.dataset.srcset;
                        }
                        imageObserver.unobserve(img);
                    }
                });
            });
            
            document.querySelectorAll('img[data-src]').forEach(img => {
                imageObserver.observe(img);
            });
        } else {
            // Fallback
            $('img[data-src]').each(function() {
                $(this).attr('src', $(this).data('src'));
            });
        }
    },
    
    // =========================================
    // AUTO REFRESH
    // =========================================
    
    /**
     * Initialize auto-refresh for containers
     */
    initAutoRefresh: function() {
        $('[data-auto-refresh]').each((index, element) => {
            const $el = $(element);
            const interval = $el.data('refresh-interval') || 30000; // 30 seconds default
            const url = $el.data('refresh-url') || window.location.href;
            
            setInterval(() => {
                this.refreshContainer($el, url);
            }, interval);
        });
    },
    
    /**
     * Refresh a container
     */
    refreshContainer: function(container, url) {
        this.loadUrl(url, {
            target: container,
            method: 'GET',
            useCache: false,
            showLoading: false
        });
    },
    
    // =========================================
    // HELPER FUNCTIONS
    // =========================================
    
    /**
     * Show loading indicator
     */
    showLoading: function(target) {
        $(target).addClass('loading');
        const $loader = $('<div class="ajax-loader"><div class="spinner-border text-primary"></div></div>');
        $(target).append($loader);
    },
    
    /**
     * Hide loading indicator
     */
    hideLoading: function(target) {
        $(target).removeClass('loading');
        $(target).find('.ajax-loader').remove();
    },
    
    /**
     * Show error message
     */
    showError: function(target, message) {
        $(target).html(this.formatMessage('error', message));
    },
    
    /**
     * Format message HTML
     */
    formatMessage: function(type, message) {
        const icons = {
            success: 'fa-check-circle',
            error: 'fa-times-circle',
            warning: 'fa-exclamation-triangle',
            info: 'fa-info-circle'
        };
        
        return `
            <div class="alert alert-${type} alert-dismissible fade show" role="alert">
                <i class="fas ${icons[type] || 'fa-info-circle'} mr-2"></i>
                ${message}
                <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                    <span aria-hidden="true">&times;</span>
                </button>
            </div>
        `;
    },
    
    /**
     * Reinitialize components in loaded content
     */
    reinitializeComponents: function(container) {
        const $container = $(container);
        
        // Reinitialize tooltips
        $container.find('[data-toggle="tooltip"]').each(function() {
            new bootstrap.Tooltip(this);
        });
        
        // Reinitialize popovers
        $container.find('[data-toggle="popover"]').each(function() {
            new bootstrap.Popover(this);
        });
        
        // Reinitialize select2
        $container.find('.select2').select2({
            theme: 'bootstrap-5',
            width: '100%'
        });
        
        // Reinitialize datepickers
        $container.find('.datepicker').datepicker({
            format: 'yyyy-mm-dd',
            autoclose: true,
            todayHighlight: true
        });
        
        // Trigger custom event
        $(document).trigger('ajax:reinitialized', [container]);
    },
    
    /**
     * Reload a container by selector
     */
    reloadContainer: function(selector) {
        this.loadUrl(window.location.href, {
            target: selector,
            method: 'GET',
            useCache: false,
            replace: true
        });
    },
    
    /**
     * Clear cache
     */
    clearCache: function() {
        this.cache.clear();
    },
    
    /**
     * Cancel all active requests
     */
    cancelAllRequests: function() {
        this.activeRequests.forEach(requestId => {
            this.activeRequests.delete(requestId);
        });
    },
    
    /**
     * Debounce helper
     */
    debounce: function(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    },
    
    /**
     * Throttle helper
     */
    throttle: function(func, limit) {
        let inThrottle;
        return function(...args) {
            if (!inThrottle) {
                func.apply(this, args);
                inThrottle = true;
                setTimeout(() => inThrottle = false, limit);
            }
        };
    }
};

// =============================================
// REAL-TIME UPDATES MODULE
// =============================================
const RealtimeUpdates = {
    socket: null,
    reconnectAttempts: 0,
    maxReconnectAttempts: 5,
    reconnectDelay: 3000,
    
    /**
     * Initialize real-time updates
     */
    init: function() {
        if (typeof Pusher !== 'undefined') {
            this.initPusher();
        } else if (typeof Echo !== 'undefined') {
            this.initLaravelEcho();
        } else {
            this.initPolling();
        }
    },
    
    /**
     * Initialize Pusher
     */
    initPusher: function() {
        // Enable pusher logging - don't include in production
        // Pusher.logToConsole = true;
        
        this.socket = new Pusher('your-pusher-key', {
            cluster: 'your-pusher-cluster',
            encrypted: true
        });
        
        // Subscribe to channels
        const channel = this.socket.subscribe('ruhondo-hms');
        
        // New notification
        channel.bind('new-notification', (data) => {
            this.handleNewNotification(data);
        });
        
        // Room status update
        channel.bind('room-status-update', (data) => {
            this.handleRoomStatusUpdate(data);
        });
        
        // New reservation
        channel.bind('new-reservation', (data) => {
            this.handleNewReservation(data);
        });
        
        // POS sale
        channel.bind('pos-sale', (data) => {
            this.handlePosSale(data);
        });
    },
    
    /**
     * Initialize polling fallback
     */
    initPolling: function() {
        setInterval(() => {
            this.pollUpdates();
        }, 10000); // Poll every 10 seconds
    },
    
    /**
     * Poll for updates
     */
    pollUpdates: function() {
        $.ajax({
            url: App.config.baseUrl + '/api/updates.php',
            method: 'GET',
            success: (response) => {
                if (response.data) {
                    this.processUpdates(response.data);
                }
            }
        });
    },
    
    /**
     * Process polled updates
     */
    processUpdates: function(updates) {
        if (updates.notifications) {
            updates.notifications.forEach(n => this.handleNewNotification(n));
        }
        if (updates.rooms) {
            updates.rooms.forEach(r => this.handleRoomStatusUpdate(r));
        }
        if (updates.reservations) {
            updates.reservations.forEach(r => this.handleNewReservation(r));
        }
        if (updates.pos_sales) {
            updates.pos_sales.forEach(s => this.handlePosSale(s));
        }
    },
    
    /**
     * Handle new notification
     */
    handleNewNotification: function(data) {
        // Play sound
        this.playNotificationSound();
        
        // Show toast
        App.showToast(data.message, data.type || 'info', data.title || 'New Notification');
        
        // Update notification badge
        App.loadNotifications();
        
        // Trigger event
        $(document).trigger('realtime:notification', [data]);
    },
    
    /**
     * Handle room status update
     */
    handleRoomStatusUpdate: function(data) {
        // Update room status in UI
        const $room = $(`[data-room-id="${data.room_id}"]`);
        if ($room.length) {
            $room.removeClass('available occupied maintenance housekeeping')
                  .addClass(data.status)
                  .find('.room-status')
                  .text(data.status_display);
        }
        
        // Show toast
        App.showToast(`Room ${data.room_number} status changed to ${data.status_display}`, 'info');
        
        // Trigger event
        $(document).trigger('realtime:room-status', [data]);
    },
    
    /**
     * Handle new reservation
     */
    handleNewReservation: function(data) {
        // Play sound
        this.playNotificationSound();
        
        // Show toast
        App.showToast(`New reservation: ${data.guest_name}`, 'success', 'New Booking');
        
        // Update reservations list if on dashboard
        if ($('#recent-reservations').length) {
            AjaxLoader.reloadContainer('#recent-reservations');
        }
        
        // Trigger event
        $(document).trigger('realtime:reservation', [data]);
    },
    
    /**
     * Handle POS sale
     */
    handlePosSale: function(data) {
        // Update POS dashboard if visible
        if ($('#pos-summary').length) {
            AjaxLoader.reloadContainer('#pos-summary');
        }
        
        // Trigger event
        $(document).trigger('realtime:pos-sale', [data]);
    },
    
    /**
     * Play notification sound
     */
    playNotificationSound: function() {
        if (Notification.permission === 'granted') {
            const audio = new Audio('/assets/sounds/notification.mp3');
            audio.play().catch(e => console.log('Audio play failed:', e));
        }
    },
    
    /**
     * Request notification permission
     */
    requestNotificationPermission: function() {
        if (Notification.permission !== 'granted') {
            Notification.requestPermission();
        }
    }
};

// =============================================
// SEARCH MODULE
// =============================================
const GlobalSearch = {
    initialized: false,
    
    /**
     * Initialize global search
     */
    init: function() {
        if (this.initialized) return;
        
        this.createSearchModal();
        this.setupEventListeners();
        this.initialized = true;
    },
    
    /**
     * Create search modal
     */
    createSearchModal: function() {
        const modalHtml = `
            <div class="modal fade" id="globalSearchModal" tabindex="-1">
                <div class="modal-dialog modal-lg">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5 class="modal-title">Global Search</h5>
                            <button type="button" class="close" data-dismiss="modal">
                                <span>&times;</span>
                            </button>
                        </div>
                        <div class="modal-body">
                            <div class="input-group mb-3">
                                <input type="text" class="form-control form-control-lg" 
                                       id="globalSearchInput" placeholder="Search guests, reservations, rooms...">
                                <div class="input-group-append">
                                    <span class="input-group-text"><i class="fas fa-search"></i></span>
                                </div>
                            </div>
                            <div id="searchResults" style="max-height: 400px; overflow-y: auto;"></div>
                        </div>
                    </div>
                </div>
            </div>
        `;
        
        $('body').append(modalHtml);
    },
    
    /**
     * Setup event listeners
     */
    setupEventListeners: function() {
        // Global keyboard shortcut (Ctrl+K)
        $(document).on('keydown', (e) => {
            if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
                e.preventDefault();
                $('#globalSearchModal').modal('show');
                setTimeout(() => $('#globalSearchInput').focus(), 500);
            }
        });
        
        // Search input handler
        $('#globalSearchInput').on('input', this.debounce(() => {
            this.performSearch();
        }, 300));
        
        // Search on Enter
        $('#globalSearchInput').on('keypress', (e) => {
            if (e.which === 13) {
                e.preventDefault();
                this.performSearch();
            }
        });
    },
    
    /**
     * Perform search
     */
    performSearch: function() {
        const query = $('#globalSearchInput').val().trim();
        
        if (query.length < 2) {
            $('#searchResults').html('<div class="text-center text-muted py-4">Type at least 2 characters to search</div>');
            return;
        }
        
        $('#searchResults').html('<div class="text-center py-4"><div class="spinner-border text-primary"></div></div>');
        
        $.ajax({
            url: App.config.baseUrl + '/api/search.php',
            method: 'POST',
            data: {
                query: query,
                csrf_token: App.config.csrfToken
            },
            success: (response) => {
                if (response.status === 'success') {
                    this.displayResults(response.data);
                } else {
                    $('#searchResults').html(`<div class="alert alert-danger">${response.message}</div>`);
                }
            },
            error: () => {
                $('#searchResults').html('<div class="alert alert-danger">Search failed</div>');
            }
        });
    },
    
    /**
     * Display search results
     */
    displayResults: function(results) {
        if (!results || Object.keys(results).length === 0) {
            $('#searchResults').html('<div class="text-center text-muted py-4">No results found</div>');
            return;
        }
        
        let html = '';
        
        // Guests
        if (results.guests && results.guests.length > 0) {
            html += '<h6 class="dropdown-header">Guests</h6>';
            results.guests.forEach(guest => {
                html += `
                    <a href="${App.config.baseUrl}/guests/guests/view.php?id=${guest.guest_id}" 
                       class="dropdown-item" onclick="$('#globalSearchModal').modal('hide')">
                        <i class="fas fa-user mr-2"></i>
                        ${guest.first_name} ${guest.last_name}
                        <small class="text-muted d-block">${guest.email} | ${guest.phone}</small>
                    </a>
                `;
            });
        }
        
        // Reservations
        if (results.reservations && results.reservations.length > 0) {
            html += '<div class="dropdown-divider"></div>';
            html += '<h6 class="dropdown-header">Reservations</h6>';
            results.reservations.forEach(res => {
                html += `
                    <a href="${App.config.baseUrl}/reservations/reservations/view.php?id=${res.reservation_id}" 
                       class="dropdown-item" onclick="$('#globalSearchModal').modal('hide')">
                        <i class="fas fa-calendar-check mr-2"></i>
                        ${res.booking_code} - ${res.guest_name}
                        <small class="text-muted d-block">${res.check_in_date} to ${res.check_out_date}</small>
                    </a>
                `;
            });
        }
        
        // Rooms
        if (results.rooms && results.rooms.length > 0) {
            html += '<div class="dropdown-divider"></div>';
            html += '<h6 class="dropdown-header">Rooms</h6>';
            results.rooms.forEach(room => {
                html += `
                    <a href="${App.config.baseUrl}/rooms/rooms/view.php?id=${room.room_id}" 
                       class="dropdown-item" onclick="$('#globalSearchModal').modal('hide')">
                        <i class="fas fa-bed mr-2"></i>
                        Room ${room.room_number} - ${room.type_name}
                        <span class="badge badge-${room.status} float-right">${room.status}</span>
                    </a>
                `;
            });
        }
        
        // Invoices
        if (results.invoices && results.invoices.length > 0) {
            html += '<div class="dropdown-divider"></div>';
            html += '<h6 class="dropdown-header">Invoices</h6>';
            results.invoices.forEach(inv => {
                html += `
                    <a href="${App.config.baseUrl}/billing/invoices/view.php?id=${inv.invoice_id}" 
                       class="dropdown-item" onclick="$('#globalSearchModal').modal('hide')">
                        <i class="fas fa-file-invoice mr-2"></i>
                        ${inv.invoice_number} - ${inv.guest_name}
                        <span class="float-right">${App.formatCurrency(inv.total_amount)}</span>
                    </a>
                `;
            });
        }
        
        $('#searchResults').html(html);
    },
    
    /**
     * Debounce helper
     */
    debounce: function(func, wait) {
        let timeout;
        return function(...args) {
            clearTimeout(timeout);
            timeout = setTimeout(() => func.apply(this, args), wait);
        };
    }
};

// =============================================
// SHORTCUTS MODULE
// =============================================
const KeyboardShortcuts = {
    shortcuts: {
        'alt+n': { action: 'new-reservation', description: 'New Reservation' },
        'alt+f': { action: 'focus-search', description: 'Focus Search' },
        'alt+p': { action: 'pos-terminal', description: 'Open POS' },
        'alt+d': { action: 'dashboard', description: 'Go to Dashboard' },
        'alt+s': { action: 'settings', description: 'Open Settings' },
        'alt+/': { action: 'show-help', description: 'Show Keyboard Shortcuts' }
    },
    
    init: function() {
        $(document).on('keydown', (e) => {
            // Check for Alt key combinations
            if (e.altKey && !e.ctrlKey && !e.metaKey) {
                const key = e.key.toLowerCase();
                const shortcut = this.shortcuts[`alt+${key}`];
                
                if (shortcut) {
                    e.preventDefault();
                    this.executeAction(shortcut.action);
                }
            }
            
            // Escape key to close modals
            if (e.key === 'Escape') {
                $('.modal.show').modal('hide');
            }
        });
    },
    
    executeAction: function(action) {
        switch(action) {
            case 'new-reservation':
                window.location.href = App.config.baseUrl + '/reservations/reservations/create.php';
                break;
            case 'focus-search':
                $('#globalSearchInput').focus();
                break;
            case 'pos-terminal':
                window.location.href = App.config.baseUrl + '/pos/sales/pos.php';
                break;
            case 'dashboard':
                window.location.href = App.config.baseUrl + '/dashboard.php';
                break;
            case 'settings':
                window.location.href = App.config.baseUrl + '/admin/settings/index.php';
                break;
            case 'show-help':
                this.showHelpModal();
                break;
        }
    },
    
    showHelpModal: function() {
        let html = '<table class="table table-sm">';
        html += '<thead><tr><th>Shortcut</th><th>Action</th></tr></thead><tbody>';
        
        $.each(this.shortcuts, (key, value) => {
            html += `<tr><td><kbd>${key}</kbd></td><td>${value.description}</td></tr>`;
        });
        
        html += '</tbody></table>';
        
        App.showAlert(html, 'Keyboard Shortcuts', 'info');
    }
};

// =============================================
// INITIALIZE ALL MODULES
// =============================================
$(document).ready(function() {
    AjaxLoader.init();
    RealtimeUpdates.init();
    GlobalSearch.init();
    KeyboardShortcuts.init();
    
    // Request notification permission
    if ('Notification' in window) {
        RealtimeUpdates.requestNotificationPermission();
    }
});