import { useState, useEffect, useRef, useCallback } from 'react';
import { cn } from '@/lib/utils';

export interface DropdownProps {
  trigger: React.ReactNode;
  children: React.ReactNode;
  align?: 'left' | 'right' | 'center';
  className?: string;
  onOpenChange?: (open: boolean) => void;
}

/**
 * Composant Dropdown réutilisable avec menu et gestion du clavier.
 */
export function Dropdown({
  trigger,
  children,
  align = 'left',
  className,
  onOpenChange,
}: DropdownProps) {
  const [open, setOpen] = useState(false);
  const containerRef = useRef<HTMLDivElement>(null);
  const menuRef = useRef<HTMLDivElement>(null);
  const triggerRef = useRef<HTMLDivElement>(null);
  const focusedIndexRef = useRef<number>(-1);

  const handleOpenChange = useCallback(
    (newOpen: boolean) => {
      setOpen(newOpen);
      onOpenChange?.(newOpen);
      if (!newOpen) {
        focusedIndexRef.current = -1;
      }
    },
    [onOpenChange],
  );

  // Fermer le dropdown quand on clique en dehors
  useEffect(() => {
    if (!open) return;

    const handleClickOutside = (event: MouseEvent) => {
      if (
        containerRef.current &&
        !containerRef.current.contains(event.target as Node)
      ) {
        handleOpenChange(false);
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    return () => {
      document.removeEventListener('mousedown', handleClickOutside);
    };
  }, [open, handleOpenChange]);

  // Gestion du clavier
  useEffect(() => {
    if (!open) return;

    const handleKeyDown = (event: KeyboardEvent) => {
      if (!menuRef.current) return;

      const focusableElements = menuRef.current.querySelectorAll<HTMLElement>(
        'button, [href], input, select, textarea, [role="menuitem"], [tabindex]:not([tabindex="-1"])',
      );

      const elements = Array.from(focusableElements);

      switch (event.key) {
        case 'Escape':
          event.preventDefault();
          handleOpenChange(false);
          triggerRef.current?.focus();
          break;

        case 'ArrowDown':
          event.preventDefault();
          focusedIndexRef.current =
            focusedIndexRef.current < elements.length - 1
              ? focusedIndexRef.current + 1
              : 0;
          elements[focusedIndexRef.current]?.focus();
          break;

        case 'ArrowUp':
          event.preventDefault();
          focusedIndexRef.current =
            focusedIndexRef.current > 0
              ? focusedIndexRef.current - 1
              : elements.length - 1;
          elements[focusedIndexRef.current]?.focus();
          break;

        case 'Enter':
        case ' ':
          event.preventDefault();
          if (
            focusedIndexRef.current >= 0 &&
            elements[focusedIndexRef.current]
          ) {
            elements[focusedIndexRef.current].click();
          }
          break;

        case 'Home':
          event.preventDefault();
          focusedIndexRef.current = 0;
          elements[0]?.focus();
          break;

        case 'End':
          event.preventDefault();
          focusedIndexRef.current = elements.length - 1;
          elements[elements.length - 1]?.focus();
          break;
      }
    };

    document.addEventListener('keydown', handleKeyDown);
    return () => {
      document.removeEventListener('keydown', handleKeyDown);
    };
  }, [open, handleOpenChange]);

  // Focuser le premier élément quand le menu s'ouvre
  useEffect(() => {
    if (open && menuRef.current) {
      const focusableElements = menuRef.current.querySelectorAll<HTMLElement>(
        'button, [href], input, select, textarea, [role="menuitem"], [tabindex]:not([tabindex="-1"])',
      );
      if (focusableElements.length > 0) {
        focusedIndexRef.current = 0;
        // Petit délai pour s'assurer que le menu est rendu
        setTimeout(() => {
          (focusableElements[0] as HTMLElement)?.focus();
        }, 0);
      }
    }
  }, [open]);

  const alignClasses = {
    left: 'left-0',
    right: 'right-0',
    center: 'left-1/2 -translate-x-1/2',
  };

  return (
    <div ref={containerRef} className={cn('relative', className)}>
      <div
        ref={triggerRef}
        onClick={() => handleOpenChange(!open)}
        role="button"
        aria-haspopup="true"
        aria-expanded={open}
        tabIndex={0}
        onKeyDown={(e) => {
          if (e.key === 'Enter' || e.key === ' ') {
            e.preventDefault();
            handleOpenChange(!open);
          } else if (e.key === 'ArrowDown') {
            e.preventDefault();
            handleOpenChange(true);
          }
        }}
        style={{ display: 'inline-block' }}
      >
        {trigger}
      </div>
      {open && (
        <>
          {/* Backdrop pour fermer en cliquant en dehors */}
          <div
            className="fixed inset-0 z-40"
            onClick={() => handleOpenChange(false)}
            aria-hidden="true"
          />
          {/* Menu */}
          <div
            ref={menuRef}
            className={cn(
              'absolute z-50 mt-2 min-w-[8rem] bg-popover border rounded-md shadow-lg',
              'overflow-hidden',
              alignClasses[align],
            )}
            role="menu"
            aria-orientation="vertical"
          >
            {children}
          </div>
        </>
      )}
    </div>
  );
}
