import React from 'react';
import { cn } from '@/lib/utils';

/**
 * DataListProps - Propriétés du composant DataList
 *
 * @interface DataListProps
 * @template T - Type des éléments de la liste
 */
interface DataListProps<T> {
  /**
   * Tableau d'éléments à afficher
   */
  items: T[];

  /**
   * Fonction pour rendre chaque élément de la liste
   *
   * @param {T} item - Élément à rendre
   * @param {number} index - Index de l'élément dans la liste
   * @returns {React.ReactNode} Élément React à afficher
   *
   * @example
   * ```tsx
   * <DataList
   *   items={users}
   *   renderItem={(user) => <div>{user.name}</div>}
   *   keyExtractor={(user) => user.id}
   * />
   * ```
   */
  renderItem: (item: T, index: number) => React.ReactNode;

  /**
   * Fonction pour extraire une clé unique de chaque élément
   *
   * @param {T} item - Élément
   * @returns {string} Clé unique
   */
  keyExtractor: (item: T) => string;

  /**
   * Message à afficher lorsque la liste est vide
   *
   * @default 'No items found'
   */
  emptyMessage?: string;

  /**
   * Si `true`, affiche un état de chargement avec des skeletons
   *
   * @default false
   */
  loading?: boolean;

  /**
   * Message d'erreur à afficher si une erreur survient
   */
  error?: string;

  /**
   * Classes CSS personnalisées pour le conteneur
   */
  className?: string;

  /**
   * Classes CSS personnalisées pour chaque élément
   */
  itemClassName?: string;
}

/**
 * DataList - Composant de liste générique avec gestion des états
 *
 * Composant réutilisable pour afficher des listes d'éléments avec support pour :
 * - État de chargement (skeletons)
 * - État d'erreur
 * - État vide
 * - Rendu personnalisé des éléments
 *
 * @example
 * ```tsx
 * // Liste simple
 * <DataList
 *   items={users}
 *   renderItem={(user) => (
 *     <div className="p-4 border">
 *       <h3>{user.name}</h3>
 *       <p>{user.email}</p>
 *     </div>
 *   )}
 *   keyExtractor={(user) => user.id}
 * />
 * ```
 *
 * @example
 * ```tsx
 * // Avec états de chargement et d'erreur
 * <DataList
 *   items={tracks}
 *   renderItem={(track) => <TrackCard track={track} />}
 *   keyExtractor={(track) => track.id}
 *   loading={isLoading}
 *   error={error}
 *   emptyMessage="Aucune piste trouvée"
 * />
 * ```
 *
 * @component
 * @template T - Type des éléments de la liste
 * @param {DataListProps<T>} props - Propriétés du composant
 * @returns {JSX.Element} Liste d'éléments avec gestion des états
 */

export function DataList<T>({
  items,
  renderItem,
  keyExtractor,
  emptyMessage = 'No items found',
  loading = false,
  error,
  className,
  itemClassName,
}: DataListProps<T>) {
  if (loading) {
    return (
      <div className={cn('space-y-2', className)}>
        {Array.from({ length: 3 }).map((_, index) => (
          <div
            key={index}
            className="animate-pulse bg-gray-200 dark:bg-gray-700 rounded h-16"
          />
        ))}
      </div>
    );
  }

  if (error) {
    return (
      <div className={cn('text-center py-8', className)}>
        <p className="text-red-500 dark:text-red-400">{error}</p>
      </div>
    );
  }

  if (items.length === 0) {
    return (
      <div className={cn('text-center py-8', className)}>
        <p className="text-gray-500 dark:text-gray-400">{emptyMessage}</p>
      </div>
    );
  }

  return (
    <div className={cn('space-y-2', className)}>
      {items.map((item, index) => (
        <div key={keyExtractor(item)} className={itemClassName}>
          {renderItem(item, index)}
        </div>
      ))}
    </div>
  );
}

/**
 * ModalProps - Propriétés du composant Modal
 *
 * @interface ModalProps
 */
interface ModalProps {
  /**
   * Si `true`, le modal est ouvert
   */
  isOpen: boolean;

  /**
   * Fonction appelée pour fermer le modal
   */
  onClose: () => void;

  /**
   * Titre du modal (affiché dans le header)
   */
  title?: string;

  /**
   * Contenu du modal
   */
  children: React.ReactNode;

  /**
   * Taille du modal
   *
   * - `sm`: max-w-md
   * - `md`: max-w-lg - par défaut
   * - `lg`: max-w-2xl
   * - `xl`: max-w-4xl
   *
   * @default 'md'
   */
  size?: 'sm' | 'md' | 'lg' | 'xl';

  /**
   * Si `true`, affiche le bouton de fermeture dans le header
   *
   * @default true
   */
  showCloseButton?: boolean;
}

/**
 * Modal - Composant de modal avec backdrop et fermeture
 *
 * Composant modal simple avec backdrop cliquable et bouton de fermeture.
 *
 * @example
 * ```tsx
 * <Modal
 *   isOpen={isOpen}
 *   onClose={() => setIsOpen(false)}
 *   title="Titre du modal"
 * >
 *   <p>Contenu du modal</p>
 * </Modal>
 * ```
 *
 * @component
 */

export const Modal: React.FC<ModalProps> = ({
  isOpen,
  onClose,
  title,
  children,
  size = 'md',
  showCloseButton = true,
}) => {
  if (!isOpen) return null;

  const sizeClasses = {
    sm: 'max-w-md',
    md: 'max-w-lg',
    lg: 'max-w-2xl',
    xl: 'max-w-4xl',
  };

  return (
    <div className="fixed inset-0 z-50 flex items-center justify-center">
      {/* Backdrop */}
      <div
        className="absolute inset-0 bg-black bg-opacity-50"
        onClick={onClose}
      />

      {/* Modal */}
      <div
        className={cn(
          'relative bg-white dark:bg-gray-800 rounded-lg shadow-xl',
          'w-full mx-4',
          sizeClasses[size],
        )}
      >
        {/* Header */}
        {(title || showCloseButton) && (
          <div className="flex items-center justify-between p-6 border-b border-gray-200 dark:border-gray-700">
            {title && (
              <h2 className="text-lg font-semibold text-gray-900 dark:text-white">
                {title}
              </h2>
            )}
            {showCloseButton && (
              <button
                onClick={onClose}
                className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300"
              >
                <svg
                  className="w-6 h-6"
                  fill="none"
                  stroke="currentColor"
                  viewBox="0 0 24 24"
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    strokeWidth={2}
                    d="M6 18L18 6M6 6l12 12"
                  />
                </svg>
              </button>
            )}
          </div>
        )}

        {/* Content */}
        <div className="p-6">{children}</div>
      </div>
    </div>
  );
};

/**
 * DropdownProps - Propriétés du composant Dropdown
 *
 * @interface DropdownProps
 */
interface DropdownProps {
  /**
   * Élément déclencheur du dropdown (bouton, etc.)
   */
  trigger: React.ReactNode;

  /**
   * Contenu du dropdown (menu items, etc.)
   */
  children: React.ReactNode;

  /**
   * Si `true`, le dropdown est ouvert
   */
  isOpen: boolean;

  /**
   * Fonction appelée pour basculer l'état ouvert/fermé
   */
  onToggle: () => void;

  /**
   * Alignement du dropdown par rapport au trigger
   *
   * - `left`: Aligné à gauche
   * - `right`: Aligné à droite
   *
   * @default 'left'
   */
  align?: 'left' | 'right';

  /**
   * Classes CSS personnalisées pour le dropdown
   */
  className?: string;
}

/**
 * Dropdown - Composant de menu déroulant basique
 *
 * Composant de dropdown avec backdrop et positionnement relatif au trigger.
 *
 * @example
 * ```tsx
 * <Dropdown
 *   trigger={<Button>Menu</Button>}
 *   isOpen={isOpen}
 *   onToggle={() => setIsOpen(!isOpen)}
 *   align="right"
 * >
 *   <div className="p-2">
 *     <button>Option 1</button>
 *     <button>Option 2</button>
 *   </div>
 * </Dropdown>
 * ```
 *
 * @component
 */

export const Dropdown: React.FC<DropdownProps> = ({
  trigger,
  children,
  isOpen,
  onToggle,
  align = 'left',
  className,
}) => {
  return (
    <div className="relative">
      <div onClick={onToggle}>{trigger}</div>

      {isOpen && (
        <>
          {/* Backdrop */}
          <div className="fixed inset-0 z-10" onClick={onToggle} />

          {/* Dropdown */}
          <div
            className={cn(
              'absolute z-20 mt-1 bg-white dark:bg-gray-800 rounded-md shadow-lg',
              'border border-gray-200 dark:border-gray-700',
              align === 'right' ? 'right-0' : 'left-0',
              className,
            )}
          >
            {children}
          </div>
        </>
      )}
    </div>
  );
};
