'use client';

import { useState, useRef, useEffect, useCallback, ReactNode } from 'react';
import { createPortal } from 'react-dom';
import { cn } from '@/lib/utils';
import { ChevronDown } from 'lucide-react';

export type DropdownPlacement =
  | 'top-start'
  | 'top'
  | 'top-end'
  | 'bottom-start'
  | 'bottom'
  | 'bottom-end'
  | 'left-start'
  | 'left'
  | 'left-end'
  | 'right-start'
  | 'right'
  | 'right-end';

export type DropdownVariant =
  | 'default'
  | 'secondary'
  | 'primary'
  | 'selected'
  | 'ghost'
  | 'custom';

interface DropdownProps {
  /** Texte du bouton déclencheur */
  trigger: ReactNode;
  /** Variant du bouton trigger */
  variant?: DropdownVariant;
  /** Contenu du dropdown */
  content: ReactNode;
  /** Position du dropdown par rapport au trigger */
  placement?: DropdownPlacement;
  /** Z-index du dropdown */
  zIndex?: number;
  /** Classe CSS additionnelle pour le dropdown */
  className?: string;
  /** Classe CSS additionnelle pour le contenu */
  contentClassName?: string;
  /** Classe CSS additionnelle pour le bouton trigger */
  triggerClassName?: string;
  /** Callback quand le dropdown s'ouvre */
  onOpen?: () => void;
  /** Callback quand le dropdown se ferme */
  onClose?: () => void;
  /** Contrôle externe de l'état ouvert/fermé */
  open?: boolean;
  /** Callback quand l'état change */
  onOpenChange?: (open: boolean) => void;
  /** Fermer quand on clique à l'extérieur */
  closeOnOutsideClick?: boolean;
  /** Fermer quand on appuie sur Escape */
  closeOnEscape?: boolean;
  /** Désactiver le dropdown */
  disabled?: boolean;
}

export function Dropdown({
  trigger,
  variant = 'default',
  content,
  placement = 'bottom-start',
  zIndex = 9999,
  className,
  contentClassName,
  triggerClassName,
  onOpen,
  onClose,
  open: controlledOpen,
  onOpenChange,
  closeOnOutsideClick = true,
  closeOnEscape = true,
  disabled = false,
}: DropdownProps) {
  const [isOpen] = useState(false);
  const [mounted, setMounted] = useState(false);
  const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });
  const [positionCalculated, setPositionCalculated] = useState(false);

  const dropdownRef = useRef<HTMLDivElement>(null);
  const triggerRef = useRef<HTMLButtonElement>(null);

  // Utiliser l'état contrôlé si fourni, sinon utiliser l'état interne
  const open = controlledOpen !== undefined ? controlledOpen : isOpen;

  // Mount check pour SSR
  useEffect(() => {
    setMounted(true);
  }, []);

  const handleOpen = () => {
    if (disabled) return;

    // Toujours appeler onOpenChange, même en mode contrôlé
    onOpenChange?.(true);
    onOpen?.();
  };

  const handleClose = useCallback(() => {
    // Toujours appeler onOpenChange, même en mode contrôlé
    onOpenChange?.(false);
    onClose?.();
  }, [onOpenChange, onClose]);

  // Calculer la position du dropdown
  const calculatePosition = useCallback(() => {
    if (!triggerRef.current) return;

    const rect = triggerRef.current.getBoundingClientRect();

    let top = 0;
    let left = 0;

    // Calculer la position selon le placement
    switch (placement) {
      case 'top-start':
        top = rect.top - 4;
        left = rect.left;
        break;
      case 'top':
        top = rect.top - 4;
        left = rect.left + rect.width / 2;
        break;
      case 'top-end':
        top = rect.top - 4;
        left = rect.right;
        break;
      case 'bottom-start':
        top = rect.bottom + 4;
        left = rect.left;
        break;
      case 'bottom':
        top = rect.bottom + 4;
        left = rect.left + rect.width / 2;
        break;
      case 'bottom-end':
        top = rect.bottom + 4;
        left = rect.right;
        break;
      case 'left-start':
        top = rect.top;
        left = rect.left - 4;
        break;
      case 'left':
        top = rect.top + rect.height / 2;
        left = rect.left - 4;
        break;
      case 'left-end':
        top = rect.bottom;
        left = rect.left - 4;
        break;
      case 'right-start':
        top = rect.top;
        left = rect.right + 4;
        break;
      case 'right':
        top = rect.top + rect.height / 2;
        left = rect.right + 4;
        break;
      case 'right-end':
        top = rect.bottom;
        left = rect.right + 4;
        break;
    }

    setDropdownPosition({ top, left });
    setPositionCalculated(true);
  }, [placement]);

  // Mettre à jour la position quand le dropdown s'ouvre
  useEffect(() => {
    if (open) {
      setPositionCalculated(false);
      calculatePosition();
    } else {
      setPositionCalculated(false);
    }
  }, [open, calculatePosition]);

  // Gérer les événements clavier
  useEffect(() => {
    if (!open || !closeOnEscape) return;

    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        handleClose();
      }
    };

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

  // Gérer les clics à l'extérieur
  useEffect(() => {
    if (!open || !closeOnOutsideClick) return;

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

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

  const handleToggle = () => {
    if (disabled) return;

    if (open) {
      handleClose();
    } else {
      handleOpen();
    }
  };

  // Styles des variants
  const getVariantStyles = () => {
    switch (variant) {
      case 'primary':
        return 'bg-[color-mix(in_srgb,var(--primary)_15%,transparent)] text-[var(--foreground)] border border-[var(--primary)] hover:bg-[color-mix(in_srgb,var(--primary)_20%,transparent)]';
      case 'secondary':
        return 'bg-[var(--card)] text-[var(--muted-foreground)] border border-[var(--border)] hover:border-[var(--primary)]/50';
      case 'selected':
        return 'bg-[color-mix(in_srgb,var(--primary)_15%,transparent)] text-[var(--foreground)] border border-[var(--primary)] hover:bg-[color-mix(in_srgb,var(--primary)_20%,transparent)]';
      case 'ghost':
        return 'text-[var(--foreground)] hover:bg-[var(--card-hover)]';
      case 'custom':
        return ''; // Pas de styles par défaut pour custom
      default:
        return 'bg-[var(--card)] text-[var(--foreground)] border border-[var(--border)] hover:bg-[var(--card-hover)]';
    }
  };

  // Créer le bouton trigger
  const triggerElement = (
    <button
      ref={triggerRef}
      onClick={(e: React.MouseEvent) => {
        e.stopPropagation(); // Empêcher la propagation vers closeOnOutsideClick
        handleToggle();
      }}
      onMouseDown={(e: React.MouseEvent) => {
        e.stopPropagation(); // Empêcher la propagation vers closeOnOutsideClick
      }}
      aria-expanded={open}
      aria-haspopup={true}
      disabled={disabled}
      className={cn(
        'flex items-center gap-2 px-3 py-2 text-sm font-medium rounded-md transition-colors',
        getVariantStyles(),
        triggerClassName,
        disabled && 'opacity-50 cursor-not-allowed'
      )}
    >
      {trigger}
      <ChevronDown
        className={`w-4 h-4 transition-transform ${open ? 'rotate-180' : ''}`}
      />
    </button>
  );

  // Contenu du dropdown
  const dropdownContent = open && mounted && positionCalculated && (
    <div
      ref={dropdownRef}
      className={cn(
        'fixed bg-[var(--card)] border border-[var(--border)] rounded-md shadow-lg',
        className
      )}
      style={{
        top: `${dropdownPosition.top}px`,
        left: `${dropdownPosition.left}px`,
        zIndex,
      }}
    >
      <div className={cn('p-3', contentClassName)}>{content}</div>
    </div>
  );

  return (
    <>
      {triggerElement}
      {mounted && createPortal(dropdownContent, document.body)}
    </>
  );
}
