/**
 * Hook pour gérer les raccourcis clavier des playlists
 * T0507: Create Playlist Keyboard Shortcuts
 * 
 * Raccourcis disponibles :
 * - Espace : play/pause du track actuel
 * - Flèche droite : track suivant
 * - Flèche gauche : track précédent
 * - 'a' ou 'A' : ajouter un track (ouvre le modal)
 * - 'Delete' ou 'Backspace' : supprimer le track sélectionné
 * 
 * @example
 * ```tsx
 * usePlaylistKeyboardShortcuts({
 *   onPlayPause: () => handlePlayPause(),
 *   onNext: () => handleNext(),
 *   onPrevious: () => handlePrevious(),
 *   onAddTrack: () => setIsAddTrackModalOpen(true),
 *   onDelete: () => handleDelete(),
 *   enabled: true,
 * });
 * ```
 */

import { useEffect, useCallback, useRef } from 'react';

export interface UsePlaylistKeyboardShortcutsOptions {
  /**
   * Callback appelé pour play/pause (Espace)
   */
  onPlayPause?: () => void;
  
  /**
   * Callback appelé pour passer au track suivant (Flèche droite)
   */
  onNext?: () => void;
  
  /**
   * Callback appelé pour revenir au track précédent (Flèche gauche)
   */
  onPrevious?: () => void;
  
  /**
   * Callback appelé pour ajouter un track (a ou A)
   */
  onAddTrack?: () => void;
  
  /**
   * Callback appelé pour supprimer un track (Delete ou Backspace)
   */
  onDelete?: () => void;
  
  /**
   * Active ou désactive les raccourcis clavier
   * @default true
   */
  enabled?: boolean;
  
  /**
   * Empêche le comportement par défaut des touches
   * @default true
   */
  preventDefault?: boolean;
  
  /**
   * Élément de référence pour limiter les raccourcis à un conteneur spécifique
   * Si non fourni, les raccourcis sont actifs sur toute la page
   */
  containerRef?: React.RefObject<HTMLElement>;
}

/**
 * Vérifie si l'utilisateur est en train de taper dans un champ de saisie
 */
function isInputElement(target: EventTarget | null): boolean {
  if (!target || !(target instanceof HTMLElement)) {
    return false;
  }
  
  const tagName = target.tagName.toLowerCase();
  const isInput = tagName === 'input' || tagName === 'textarea';
  const isContentEditable = target.isContentEditable === true;
  const isSelect = tagName === 'select';
  
  return isInput || isContentEditable || isSelect;
}

/**
 * Hook pour gérer les raccourcis clavier des playlists
 */
export function usePlaylistKeyboardShortcuts(
  options: UsePlaylistKeyboardShortcutsOptions = {}
): void {
  const {
    onPlayPause,
    onNext,
    onPrevious,
    onAddTrack,
    onDelete,
    enabled = true,
    preventDefault = true,
    containerRef,
  } = options;

  // Utiliser un ref pour stocker les callbacks afin d'éviter les re-renders
  const callbacksRef = useRef({
    onPlayPause,
    onNext,
    onPrevious,
    onAddTrack,
    onDelete,
  });

  // Mettre à jour les callbacks dans le ref
  useEffect(() => {
    callbacksRef.current = {
      onPlayPause,
      onNext,
      onPrevious,
      onAddTrack,
      onDelete,
    };
  }, [onPlayPause, onNext, onPrevious, onAddTrack, onDelete]);

  const handleKeyDown = useCallback(
    (e: KeyboardEvent) => {
      if (!enabled) return;

      // Ignorer si l'utilisateur est en train de taper dans un input/textarea
      if (isInputElement(e.target)) {
        return;
      }

      // Si un containerRef est fourni, vérifier que l'événement provient de ce conteneur
      if (containerRef?.current) {
        const container = containerRef.current;
        const target = e.target as HTMLElement;
        if (!container.contains(target)) {
          return;
        }
      }

      switch (e.code) {
        case 'Space': {
          // Espace : play/pause
          if (callbacksRef.current.onPlayPause) {
            if (preventDefault) {
              e.preventDefault();
            }
            callbacksRef.current.onPlayPause();
          }
          break;
        }

        case 'ArrowRight': {
          // Flèche droite : track suivant
          if (callbacksRef.current.onNext) {
            if (preventDefault) {
              e.preventDefault();
            }
            callbacksRef.current.onNext();
          }
          break;
        }

        case 'ArrowLeft': {
          // Flèche gauche : track précédent
          if (callbacksRef.current.onPrevious) {
            if (preventDefault) {
              e.preventDefault();
            }
            callbacksRef.current.onPrevious();
          }
          break;
        }

        case 'KeyA': {
          // 'a' ou 'A' : ajouter un track
          if (callbacksRef.current.onAddTrack) {
            if (preventDefault && !e.ctrlKey && !e.metaKey && !e.altKey) {
              e.preventDefault();
            }
            callbacksRef.current.onAddTrack();
          }
          break;
        }

        case 'Delete':
        case 'Backspace': {
          // Delete ou Backspace : supprimer un track
          if (callbacksRef.current.onDelete) {
            // Ne pas supprimer si on est dans un input
            if (isInputElement(e.target)) {
              return;
            }
            if (preventDefault) {
              e.preventDefault();
            }
            callbacksRef.current.onDelete();
          }
          break;
        }

        default:
          break;
      }
    },
    [enabled, preventDefault, containerRef]
  );

  useEffect(() => {
    if (!enabled) return;

    const target = containerRef?.current || window;
    target.addEventListener('keydown', handleKeyDown);

    return () => {
      target.removeEventListener('keydown', handleKeyDown);
    };
  }, [enabled, handleKeyDown, containerRef]);
}

export default usePlaylistKeyboardShortcuts;

