/**
 * @moduleName: EventManagement
 * @version: 2.0.0
 * @since: 2025-07-26
 * @lastUpdated: 2025-07-26
 * @projectSummary: Enhanced MCP Quiz Server - Event Management System
 * @techStack: TypeScript, DOM API, Event Delegation
 * @dependency: None (core utility)
 * @interModuleDependency: Used by QuizContent, AnswerHandler, NavigationController
 * @requirementsTraceability:
 *   {@link Requirements.REQ_UI_003} (Event Handling)
 *   {@link Requirements.REQ_BUG_021} (Infinite Recursion Fix)
 * @briefDescription: Centralized event management system preventing memory leaks and infinite recursion
 * @methods: addListener, removeListener, cleanup, delegate
 * @contributors: GitHub Copilot
 * @examples:
 *   - EventManagement.addListener(button, 'click', handler, 'continue-button')
 *   - EventManagement.cleanup(['continue-button', 'complete-button'])
 * @vulnerabilitiesAssessment: Memory leak prevention, proper event cleanup, no sensitive data
 */

export class EventManagement {
  private static eventListeners = new Map<
    string,
    {
      element: Element;
      event: string;
      handler: EventListener;
    }
  >();

  /**
   * Add an event listener with automatic cleanup of existing listeners
   * @param element - The DOM element to attach the listener to
   * @param event - The event type (e.g., 'click', 'keydown')
   * @param handler - The event handler function
   * @param key - Unique key for this listener (enables cleanup)
   */
  static addListener(element: Element, event: string, handler: EventListener, key: string): void {
    // Remove existing listener if present to prevent duplicates
    if (this.eventListeners.has(key)) {
      const existing = this.eventListeners.get(key)!;
      existing.element.removeEventListener(existing.event, existing.handler);
    }

    // Add new listener
    element.addEventListener(event, handler);
    this.eventListeners.set(key, {
      element,
      event,
      handler,
    });

    console.log(`🔗 Event listener added: ${key} (${event})`);
  }

  /**
   * Remove a specific event listener
   * @param key - The unique key of the listener to remove
   */
  static removeListener(key: string): void {
    if (this.eventListeners.has(key)) {
      const listener = this.eventListeners.get(key)!;
      listener.element.removeEventListener(listener.event, listener.handler);
      this.eventListeners.delete(key);
      console.log(`🗑️ Event listener removed: ${key}`);
    }
  }

  /**
   * Clean up multiple listeners by their keys
   * @param keys - Array of listener keys to clean up, or undefined to clean all
   */
  static cleanup(keys?: string[]): void {
    const keysToClean = keys || Array.from(this.eventListeners.keys());

    keysToClean.forEach(key => {
      this.removeListener(key);
    });

    console.log(`🧹 Event cleanup completed: ${keysToClean.length} listeners removed`);
  }

  /**
   * Get the count of active listeners (for debugging)
   */
  static getActiveListenerCount(): number {
    return this.eventListeners.size;
  }

  /**
   * Get all active listener keys (for debugging)
   */
  static getActiveListenerKeys(): string[] {
    return Array.from(this.eventListeners.keys());
  }

  /**
   * Event delegation helper for dynamic content
   * @param container - The container element to delegate from
   * @param selector - CSS selector for target elements
   * @param event - Event type to listen for
   * @param handler - Event handler function
   * @param key - Unique key for cleanup
   */
  static delegate(
    container: Element,
    selector: string,
    event: string,
    handler: (event: Event, target: Element) => void,
    key: string
  ): void {
    const delegatedHandler = (e: Event) => {
      const target = (e.target as Element).closest(selector);
      if (target) {
        handler(e, target);
      }
    };

    this.addListener(container, event, delegatedHandler, key);
  }

  /**
   * Safe cleanup for component destruction
   * Call this when a component is being destroyed to prevent memory leaks
   */
  static componentCleanup(componentPrefix: string): void {
    const componentKeys = Array.from(this.eventListeners.keys()).filter(key =>
      key.startsWith(componentPrefix)
    );

    this.cleanup(componentKeys);
    console.log(`🏗️ Component cleanup: ${componentPrefix} (${componentKeys.length} listeners)`);
  }
}
