// Accessibility utilities and helpers

/**
 * Generate unique IDs for form elements and ARIA relationships
 */
export function generateUniqueId(prefix: string = 'element'): string {
  return `${prefix}-${Math.random().toString(36).substr(2, 9)}`;
}

/**
 * Announce messages to screen readers
 */
export function announceToScreenReader(message: string, priority: 'polite' | 'assertive' = 'polite') {
  const announcement = document.createElement('div');
  announcement.setAttribute('aria-live', priority);
  announcement.setAttribute('aria-atomic', 'true');
  announcement.className = 'sr-only';
  announcement.textContent = message;
  
  document.body.appendChild(announcement);
  
  // Remove after announcement
  setTimeout(() => {
    document.body.removeChild(announcement);
  }, 1000);
}

/**
 * Manage focus for modal dialogs
 */
export class FocusManager {
  private focusableElements: NodeListOf<HTMLElement> | null = null;
  private firstFocusableElement: HTMLElement | null = null;
  private lastFocusableElement: HTMLElement | null = null;
  private previouslyFocusedElement: HTMLElement | null = null;

  /**
   * Initialize focus management for a container
   */
  public init(container: HTMLElement) {
    this.previouslyFocusedElement = document.activeElement as HTMLElement;
    this.focusableElements = container.querySelectorAll(
      'a[href], button, textarea, input[type="text"], input[type="radio"], input[type="checkbox"], select, [tabindex]:not([tabindex="-1"])'
    );
    
    if (this.focusableElements.length > 0) {
      this.firstFocusableElement = this.focusableElements[0];
      this.lastFocusableElement = this.focusableElements[this.focusableElements.length - 1];
      
      // Focus first element
      this.firstFocusableElement.focus();
    }
  }

  /**
   * Handle keyboard navigation within the container
   */
  public handleKeyDown(event: KeyboardEvent) {
    if (event.key !== 'Tab') return;

    if (event.shiftKey) {
      // Shift + Tab
      if (document.activeElement === this.firstFocusableElement) {
        event.preventDefault();
        this.lastFocusableElement?.focus();
      }
    } else {
      // Tab
      if (document.activeElement === this.lastFocusableElement) {
        event.preventDefault();
        this.firstFocusableElement?.focus();
      }
    }
  }

  /**
   * Restore focus to previously focused element
   */
  public restoreFocus() {
    if (this.previouslyFocusedElement) {
      this.previouslyFocusedElement.focus();
    }
  }
}

/**
 * Skip link functionality
 */
export function initializeSkipLinks() {
  const skipLinks = document.querySelectorAll('.skip-link');
  
  skipLinks.forEach(link => {
    link.addEventListener('click', (event) => {
      event.preventDefault();
      const target = document.querySelector((event.target as HTMLAnchorElement).getAttribute('href')!);
      if (target) {
        (target as HTMLElement).focus();
        target.scrollIntoView();
      }
    });
  });
}

/**
 * Enhance form accessibility
 */
export function enhanceFormAccessibility() {
  const forms = document.querySelectorAll('form');
  
  forms.forEach(form => {
    // Add ARIA labels to form controls without labels
    const inputs = form.querySelectorAll('input, select, textarea');
    inputs.forEach(input => {
      if (!input.getAttribute('aria-label') && !input.getAttribute('aria-labelledby')) {
        const label = form.querySelector(`label[for="${input.id}"]`);
        if (!label && input.getAttribute('placeholder')) {
          input.setAttribute('aria-label', input.getAttribute('placeholder')!);
        }
      }
    });

    // Add error message associations
    const errorMessages = form.querySelectorAll('[data-error-for]');
    errorMessages.forEach(error => {
      const inputId = error.getAttribute('data-error-for');
      const input = form.querySelector(`#${inputId}`);
      if (input) {
        const errorId = generateUniqueId('error');
        error.id = errorId;
        input.setAttribute('aria-describedby', errorId);
        input.setAttribute('aria-invalid', 'true');
      }
    });
  });
}

/**
 * Add keyboard navigation to custom components
 */
export function addKeyboardNavigation() {
  // Custom dropdown navigation
  const dropdowns = document.querySelectorAll('[role="combobox"]');
  dropdowns.forEach(dropdown => {
    dropdown.addEventListener('keydown', (event) => {
      const key = event.key;
      if (key === 'ArrowDown' || key === 'ArrowUp') {
        event.preventDefault();
        // Handle dropdown navigation
      } else if (key === 'Escape') {
        // Close dropdown
        dropdown.blur();
      }
    });
  });

  // Tab navigation for card grids
  const cardGrids = document.querySelectorAll('[data-card-grid]');
  cardGrids.forEach(grid => {
    const cards = grid.querySelectorAll('[data-card]');
    cards.forEach((card, index) => {
      card.addEventListener('keydown', (event) => {
        const key = event.key;
        let nextIndex = index;
        
        if (key === 'ArrowRight' || key === 'ArrowDown') {
          nextIndex = Math.min(index + 1, cards.length - 1);
        } else if (key === 'ArrowLeft' || key === 'ArrowUp') {
          nextIndex = Math.max(index - 1, 0);
        } else if (key === 'Home') {
          nextIndex = 0;
        } else if (key === 'End') {
          nextIndex = cards.length - 1;
        }
        
        if (nextIndex !== index) {
          event.preventDefault();
          (cards[nextIndex] as HTMLElement).focus();
        }
      });
    });
  });
}

/**
 * Improve color contrast for dynamic content
 */
export function validateColorContrast() {
  // This would typically integrate with a color contrast checking library

}

/**
 * Initialize all accessibility enhancements
 */
export function initializeAccessibility() {
  // Wait for DOM to be ready
  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', () => {
      initializeSkipLinks();
      enhanceFormAccessibility();
      addKeyboardNavigation();
      validateColorContrast();
    });
  } else {
    initializeSkipLinks();
    enhanceFormAccessibility();
    addKeyboardNavigation();
    validateColorContrast();
  }
}

/**
 * Screen reader utility class
 */
export class ScreenReaderSupport {
  private static liveRegion: HTMLElement | null = null;

  public static announce(message: string, priority: 'off' | 'polite' | 'assertive' = 'polite') {
    if (!this.liveRegion) {
      this.createLiveRegion();
    }
    
    if (this.liveRegion) {
      this.liveRegion.setAttribute('aria-live', priority);
      this.liveRegion.textContent = message;
      
      // Clear after announcement
      setTimeout(() => {
        if (this.liveRegion) {
          this.liveRegion.textContent = '';
        }
      }, 1000);
    }
  }

  private static createLiveRegion() {
    this.liveRegion = document.createElement('div');
    this.liveRegion.className = 'sr-only';
    this.liveRegion.setAttribute('aria-live', 'polite');
    this.liveRegion.setAttribute('aria-atomic', 'true');
    document.body.appendChild(this.liveRegion);
  }
}

/**
 * High contrast mode detection and support
 */
export function initializeHighContrastSupport() {
  // Detect if user prefers high contrast
  const prefersHighContrast = window.matchMedia('(prefers-contrast: high)');
  
  function applyHighContrast(matches: boolean) {
    if (matches) {
      document.documentElement.classList.add('high-contrast');
    } else {
      document.documentElement.classList.remove('high-contrast');
    }
  }
  
  applyHighContrast(prefersHighContrast.matches);
  prefersHighContrast.addEventListener('change', (e) => applyHighContrast(e.matches));
}

/**
 * Reduced motion support
 */
export function initializeReducedMotionSupport() {
  const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
  
  function applyReducedMotion(matches: boolean) {
    if (matches) {
      document.documentElement.classList.add('reduce-motion');
    } else {
      document.documentElement.classList.remove('reduce-motion');
    }
  }
  
  applyReducedMotion(prefersReducedMotion.matches);
  prefersReducedMotion.addEventListener('change', (e) => applyReducedMotion(e.matches));
}