/**
 * KeyboardNavigation - WCAG 2.1 AA Compliant Keyboard Navigation
 * 
 * Features:
 * - Full keyboard navigation support
 * - Focus management
 * - Skip links functionality
 * - Custom keyboard shortcuts
 * - Focus trap for modals
 * - WCAG 2.1 AA compliance
 */
class KeyboardNavigation {
    constructor() {
        this.focusableElements = 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
        this.currentFocusIndex = -1;
        this.focusableElementsList = [];
        this.modalOpen = false;
        this.lastFocusedElement = null;
        
        this.init();
    }
    
    /**
     * Initialize keyboard navigation
     */
    init() {
        this.setupEventListeners();
        this.setupSkipLinks();
        this.setupFocusManagement();
        this.setupKeyboardShortcuts();
        this.announceToScreenReader('Keyboard navigation initialized');
    }
    
    /**
     * Setup event listeners for keyboard navigation
     */
    setupEventListeners() {
        document.addEventListener('keydown', (e) => this.handleKeyDown(e));
        document.addEventListener('focus', (e) => this.handleFocus(e), true);
        document.addEventListener('blur', (e) => this.handleBlur(e), true);
        
        // Handle focus for dynamic content
        const observer = new MutationObserver(() => {
            this.updateFocusableElements();
        });
        
        observer.observe(document.body, {
            childList: true,
            subtree: true,
            attributes: true,
            attributeFilter: ['tabindex', 'disabled', 'aria-hidden']
        });
    }
    
    /**
     * Handle keyboard events
     * 
     * @param {KeyboardEvent} e Keyboard event
     */
    handleKeyDown(e) {
        switch (e.key) {
            case 'Tab':
                this.handleTabNavigation(e);
                break;
            case 'Enter':
            case ' ':
                this.handleActivation(e);
                break;
            case 'Escape':
                this.handleEscape(e);
                break;
            case 'ArrowUp':
            case 'ArrowDown':
            case 'ArrowLeft':
            case 'ArrowRight':
                this.handleArrowNavigation(e);
                break;
            case 'Home':
            case 'End':
                this.handleHomeEndNavigation(e);
                break;
            default:
                this.handleCustomShortcuts(e);
        }
    }
    
    /**
     * Handle Tab navigation
     * 
     * @param {KeyboardEvent} e Keyboard event
     */
    handleTabNavigation(e) {
        if (e.ctrlKey || e.altKey) return;
        
        this.updateFocusableElements();
        
        if (this.focusableElementsList.length === 0) return;
        
        const currentIndex = this.focusableElementsList.indexOf(document.activeElement);
        let nextIndex;
        
        if (e.shiftKey) {
            // Shift+Tab - Previous element
            nextIndex = currentIndex <= 0 ? this.focusableElementsList.length - 1 : currentIndex - 1;
        } else {
            // Tab - Next element
            nextIndex = currentIndex >= this.focusableElementsList.length - 1 ? 0 : currentIndex + 1;
        }
        
        e.preventDefault();
        this.focusElement(this.focusableElementsList[nextIndex]);
    }
    
    /**
     * Handle activation (Enter/Space)
     * 
     * @param {KeyboardEvent} e Keyboard event
     */
    handleActivation(e) {
        const element = document.activeElement;
        
        if (e.key === ' ' && (element.tagName === 'BUTTON' || element.role === 'button')) {
            e.preventDefault();
            element.click();
            this.announceToScreenReader('Button activated');
        }
        
        if (e.key === 'Enter' && element.tagName === 'A' && element.getAttribute('role') === 'menuitem') {
            e.preventDefault();
            element.click();
            this.announceToScreenReader('Link activated');
        }
    }
    
    /**
     * Handle Escape key
     * 
     * @param {KeyboardEvent} e Keyboard event
     */
    handleEscape(e) {
        if (this.modalOpen) {
            this.closeModal();
            this.announceToScreenReader('Modal closed');
        } else {
            // Return focus to main content
            const mainContent = document.getElementById('main-content');
            if (mainContent) {
                this.focusElement(mainContent);
                this.announceToScreenReader('Returned to main content');
            }
        }
    }
    
    /**
     * Handle arrow key navigation
     * 
     * @param {KeyboardEvent} e Keyboard event
     */
    handleArrowNavigation(e) {
        const element = document.activeElement;
        
        // Handle menu navigation
        if (element.getAttribute('role') === 'menuitem' || element.classList.contains('dropdown-item')) {
            e.preventDefault();
            this.navigateMenu(e.key);
        }
        
        // Handle tab navigation in tab lists
        if (element.getAttribute('role') === 'tab') {
            e.preventDefault();
            this.navigateTabs(e.key);
        }
        
        // Handle grid navigation
        if (element.getAttribute('role') === 'gridcell') {
            e.preventDefault();
            this.navigateGrid(e.key);
        }
    }
    
    /**
     * Handle Home/End navigation
     * 
     * @param {KeyboardEvent} e Keyboard event
     */
    handleHomeEndNavigation(e) {
        if (e.ctrlKey || e.altKey) return;
        
        this.updateFocusableElements();
        
        if (this.focusableElementsList.length === 0) return;
        
        const targetIndex = e.key === 'Home' ? 0 : this.focusableElementsList.length - 1;
        
        e.preventDefault();
        this.focusElement(this.focusableElementsList[targetIndex]);
        this.announceToScreenReader(`Moved to ${e.key === 'Home' ? 'first' : 'last'} element`);
    }
    
    /**
     * Setup skip links functionality
     */
    setupSkipLinks() {
        const skipLinks = document.querySelectorAll('.skip-link');
        
        skipLinks.forEach(link => {
            link.addEventListener('click', (e) => {
                e.preventDefault();
                const targetId = link.getAttribute('href').substring(1);
                const targetElement = document.getElementById(targetId);
                
                if (targetElement) {
                    this.focusElement(targetElement);
                    this.announceToScreenReader(`Skipped to ${link.textContent}`);
                }
            });
        });
    }
    
    /**
     * Setup focus management
     */
    setupFocusManagement() {
        // Add focus indicators
        const style = document.createElement('style');
        style.textContent = `
            :focus {
                outline: 3px solid #0056b3 !important;
                outline-offset: 2px !important;
            }
            
            .skip-link:focus {
                position: static !important;
                width: auto !important;
                height: auto !important;
                overflow: visible !important;
                clip: auto !important;
                clip-path: none !important;
                white-space: normal !important;
            }
            
            [aria-hidden="true"] {
                display: none !important;
            }
            
            .sr-only {
                position: absolute !important;
                width: 1px !important;
                height: 1px !important;
                padding: 0 !important;
                margin: -1px !important;
                overflow: hidden !important;
                clip: rect(0, 0, 0, 0) !important;
                white-space: nowrap !important;
                border: 0 !important;
            }
            
            .keyboard-user *:focus {
                outline: 3px solid #0056b3 !important;
                outline-offset: 2px !important;
            }
        `;
        document.head.appendChild(style);
        
        // Detect keyboard user
        document.addEventListener('keydown', () => {
            document.body.classList.add('keyboard-user');
        }, { once: true });
        
        // Remove keyboard class on mouse use
        document.addEventListener('mousedown', () => {
            document.body.classList.remove('keyboard-user');
        });
    }
    
    /**
     * Setup custom keyboard shortcuts
     */
    setupKeyboardShortcuts() {
        // Alt+S - Focus search
        this.addShortcut('Alt+s', () => {
            const searchInput = document.getElementById('search-input');
            if (searchInput) {
                this.focusElement(searchInput);
                this.announceToScreenReader('Search focused');
            }
        });
        
        // Alt+N - Focus navigation
        this.addShortcut('Alt+n', () => {
            const navigation = document.getElementById('main-navigation');
            if (navigation) {
                this.focusElement(navigation.querySelector('[role="menuitem"]'));
                this.announceToScreenReader('Navigation focused');
            }
        });
        
        // Alt+M - Focus main content
        this.addShortcut('Alt+m', () => {
            const mainContent = document.getElementById('main-content');
            if (mainContent) {
                this.focusElement(mainContent);
                this.announceToScreenReader('Main content focused');
            }
        });
        
        // Alt+H - Go home
        this.addShortcut('Alt+h', () => {
            window.location.href = '/';
        });
        
        // Alt+1-9 - Quick navigation
        for (let i = 1; i <= 9; i++) {
            this.addShortcut(`Alt+${i}`, () => {
                this.quickNavigate(i);
            });
        }
    }
    
    /**
     * Add keyboard shortcut
     * 
     * @param {string} shortcut Shortcut combination
     * @param {Function} callback Callback function
     */
    addShortcut(shortcut, callback) {
        document.addEventListener('keydown', (e) => {
            if (this.matchesShortcut(e, shortcut)) {
                e.preventDefault();
                callback();
            }
        });
    }
    
    /**
     * Check if event matches shortcut
     * 
     * @param {KeyboardEvent} e Keyboard event
     * @param {string} shortcut Shortcut string
     * @return {boolean} True if matches
     */
    matchesShortcut(e, shortcut) {
        const parts = shortcut.toLowerCase().split('+');
        const key = parts.pop();
        
        if (e.key.toLowerCase() !== key) return false;
        
        const altRequired = parts.includes('alt');
        const ctrlRequired = parts.includes('ctrl');
        const shiftRequired = parts.includes('shift');
        
        return e.altKey === altRequired && 
               e.ctrlKey === ctrlRequired && 
               e.shiftKey === shiftRequired;
    }
    
    /**
     * Update focusable elements list
     */
    updateFocusableElements() {
        this.focusableElementsList = Array.from(document.querySelectorAll(this.focusableElements))
            .filter(element => {
                // Filter out hidden elements
                const style = window.getComputedStyle(element);
                return style.display !== 'none' && 
                       style.visibility !== 'hidden' && 
                       element.getAttribute('aria-hidden') !== 'true' &&
                       !element.disabled;
            });
    }
    
    /**
     * Focus element with accessibility
     * 
     * @param {Element} element Element to focus
     */
    focusElement(element) {
        if (!element) return;
        
        element.focus();
        
        // Scroll into view if needed
        element.scrollIntoView({
            behavior: 'smooth',
            block: 'center',
            inline: 'nearest'
        });
    }
    
    /**
     * Handle focus events
     * 
     * @param {FocusEvent} e Focus event
     */
    handleFocus(e) {
        this.currentFocusIndex = this.focusableElementsList.indexOf(e.target);
        
        // Announce focus changes to screen readers
        const announcement = this.getFocusAnnouncement(e.target);
        if (announcement) {
            setTimeout(() => {
                this.announceToScreenReader(announcement);
            }, 100);
        }
    }
    
    /**
     * Handle blur events
     * 
     * @param {FocusEvent} e Blur event
     */
    handleBlur(e) {
        // Store last focused element for modal restoration
        if (!this.modalOpen) {
            this.lastFocusedElement = e.target;
        }
    }
    
    /**
     * Get focus announcement for screen readers
     * 
     * @param {Element} element Focused element
     * @return {string} Announcement text
     */
    getFocusAnnouncement(element) {
        const tagName = element.tagName.toLowerCase();
        const role = element.getAttribute('role');
        const label = element.getAttribute('aria-label') || element.textContent || '';
        
        if (role === 'button') {
            return `Button, ${label}`;
        } else if (role === 'link') {
            return `Link, ${label}`;
        } else if (tagName === 'input') {
            const type = element.type || 'text';
            return `${type} input, ${label}`;
        } else if (role === 'menuitem') {
            return `Menu item, ${label}`;
        } else if (role === 'tab') {
            return `Tab, ${label}`;
        }
        
        return label || '';
    }
    
    /**
     * Announce to screen readers
     * 
     * @param {string} message Message to announce
     */
    announceToScreenReader(message) {
        const announcement = document.createElement('div');
        announcement.setAttribute('role', 'status');
        announcement.setAttribute('aria-live', 'polite');
        announcement.className = 'sr-only';
        announcement.textContent = message;
        
        document.body.appendChild(announcement);
        
        setTimeout(() => {
            document.body.removeChild(announcement);
        }, 1000);
    }
    
    /**
     * Navigate menu with arrow keys
     * 
     * @param {string} direction Arrow direction
     */
    navigateMenu(direction) {
        const menuItems = Array.from(document.querySelectorAll('[role="menuitem"]'));
        const currentIndex = menuItems.indexOf(document.activeElement);
        
        let nextIndex;
        if (direction === 'ArrowDown' || direction === 'ArrowRight') {
            nextIndex = currentIndex >= menuItems.length - 1 ? 0 : currentIndex + 1;
        } else {
            nextIndex = currentIndex <= 0 ? menuItems.length - 1 : currentIndex - 1;
        }
        
        this.focusElement(menuItems[nextIndex]);
    }
    
    /**
     * Navigate tabs with arrow keys
     * 
     * @param {string} direction Arrow direction
     */
    navigateTabs(direction) {
        const tabs = Array.from(document.querySelectorAll('[role="tab"]'));
        const currentIndex = tabs.indexOf(document.activeElement);
        
        let nextIndex;
        if (direction === 'ArrowRight' || direction === 'ArrowDown') {
            nextIndex = currentIndex >= tabs.length - 1 ? 0 : currentIndex + 1;
        } else {
            nextIndex = currentIndex <= 0 ? tabs.length - 1 : currentIndex - 1;
        }
        
        this.focusElement(tabs[nextIndex]);
        tabs[nextIndex].click();
    }
    
    /**
     * Navigate grid with arrow keys
     * 
     * @param {string} direction Arrow direction
     */
    navigateGrid(direction) {
        // Implementation for grid navigation
        // This would need to be customized based on specific grid structure
    }
    
    /**
     * Quick navigation with Alt+number
     * 
     * @param {number} number Number key
     */
    quickNavigate(number) {
        const targets = [
            { selector: '#main-navigation', name: 'navigation' },
            { selector: '#search-input', name: 'search' },
            { selector: '#main-content', name: 'main content' },
            { selector: 'h1', name: 'heading' },
            { selector: '.breadcrumb', name: 'breadcrumb' },
            { selector: 'footer', name: 'footer' },
            { selector: '.sidebar', name: 'sidebar' },
            { selector: '.btn-primary', name: 'primary button' },
            { selector: 'form', name: 'form' }
        ];
        
        if (number <= targets.length) {
            const target = targets[number - 1];
            const element = document.querySelector(target.selector);
            if (element) {
                this.focusElement(element);
                this.announceToScreenReader(`Quick navigation to ${target.name}`);
            }
        }
    }
    
    /**
     * Handle custom shortcuts
     * 
     * @param {KeyboardEvent} e Keyboard event
     */
    handleCustomShortcuts(e) {
        // Additional custom shortcuts can be added here
    }
    
    /**
     * Open modal with focus trap
     * 
     * @param {string} modalId Modal ID
     */
    openModal(modalId) {
        const modal = document.getElementById(modalId);
        if (!modal) return;
        
        this.modalOpen = true;
        this.lastFocusedElement = document.activeElement;
        
        modal.setAttribute('aria-hidden', 'false');
        modal.style.display = 'block';
        
        // Focus first focusable element in modal
        const firstFocusable = modal.querySelector(this.focusableElements);
        if (firstFocusable) {
            this.focusElement(firstFocusable);
        }
        
        this.announceToScreenReader('Modal opened');
    }
    
    /**
     * Close modal and restore focus
     */
    closeModal() {
        if (!this.modalOpen) return;
        
        const modal = document.querySelector('[role="dialog"][aria-hidden="false"]');
        if (!modal) return;
        
        modal.setAttribute('aria-hidden', 'true');
        modal.style.display = 'none';
        
        this.modalOpen = false;
        
        // Restore focus to last focused element
        if (this.lastFocusedElement) {
            this.focusElement(this.lastFocusedElement);
        }
    }
}

// Initialize keyboard navigation when DOM is ready
document.addEventListener('DOMContentLoaded', () => {
    window.keyboardNavigation = new KeyboardNavigation();
});