/**
 * Composant TrackGrid
 * Affiche une grille de pistes avec layout responsive
 */

import React, { useState, useEffect } from 'react';
import { cn } from '@/lib/utils';
import { TrackCard } from './TrackCard';
import { TrackListSkeleton } from './TrackListSkeleton';
import { TrackListEmpty } from './TrackListEmpty';
import { TrackGridDensitySelector, type DensityMode } from './TrackGridDensitySelector';
import type { TrackListBaseProps } from '../types';
import type { Track } from '../../player/types';

export interface TrackGridProps extends TrackListBaseProps {
  columns?: 2 | 3 | 4 | 5 | 6;
  showCover?: boolean;
  showMetadata?: boolean;
  showDuration?: boolean;
  showActions?: boolean;
  isLoading?: boolean;
  emptyMessage?: string;
  emptyDescription?: string;
  emptyIcon?: 'music' | 'search' | 'filter';
  emptyAction?: React.ReactNode;
  skeletonCount?: number;
  onTrackLike?: (track: Track) => void;
  onTrackMore?: (track: Track) => void;
  isLiked?: (trackId: number) => boolean;
  isPlaying?: (trackId: number) => boolean;
  currentPlayingId?: number;
  cardSize?: 'sm' | 'md' | 'lg';
  // Options responsive
  autoColumns?: boolean; // Colonnes adaptatives basées sur la taille d'écran
  mobileColumns?: 1 | 2; // Nombre de colonnes sur mobile (défaut: 2)
  gap?: 'sm' | 'md' | 'lg'; // Espacement entre les cartes
  // Options de densité
  density?: DensityMode; // Mode de densité (compact, normal, comfortable)
  showDensitySelector?: boolean; // Afficher le sélecteur de densité
  onDensityChange?: (density: DensityMode) => void; // Callback quand la densité change
  persistDensity?: boolean; // Persister la préférence dans localStorage
  densityStorageKey?: string; // Clé pour le localStorage (défaut: 'trackGridDensity')
}

export function TrackGrid({
  tracks,
  onTrackClick,
  onTrackPlay,
  className,
  columns = 4,
  showCover = true,
  showMetadata = true,
  showDuration = true,
  showActions = true,
  isLoading = false,
  emptyMessage,
  emptyDescription,
  emptyIcon,
  emptyAction,
  skeletonCount = 8,
  onTrackLike,
  onTrackMore,
  isLiked,
  isPlaying,
  currentPlayingId,
  cardSize,
  autoColumns = false,
  mobileColumns = 2,
  gap,
  density: densityProp,
  showDensitySelector = false,
  onDensityChange,
  persistDensity = false,
  densityStorageKey = 'trackGridDensity',
}: TrackGridProps) {
  // Gérer l'état de densité avec persistance
  const [densityState, setDensityState] = useState<DensityMode>(() => {
    if (densityProp !== undefined) {
      return densityProp;
    }
    // Toujours vérifier localStorage, même si persistDensity n'est pas encore connu
    // (on l'utilisera pour décider si on doit utiliser cette valeur)
    if (typeof window !== 'undefined') {
      const stored = localStorage.getItem(densityStorageKey);
      if (stored && ['compact', 'normal', 'comfortable'].includes(stored)) {
        return stored as DensityMode;
      }
    }
    return 'normal';
  });

  // Synchroniser avec la prop si elle change
  useEffect(() => {
    if (densityProp !== undefined) {
      setDensityState(densityProp);
    }
  }, [densityProp]);

  // Persister la préférence (seulement si persistDensity est activé et qu'on a une valeur)
  useEffect(() => {
    if (persistDensity && typeof window !== 'undefined') {
      const valueToPersist = densityProp !== undefined ? densityProp : densityState;
      if (valueToPersist) {
        localStorage.setItem(densityStorageKey, valueToPersist);
      }
    }
  }, [densityState, densityProp, persistDensity, densityStorageKey]);

  // Utiliser la prop si fournie, sinon l'état local
  const currentDensity = densityProp || densityState;

  // Calculer les valeurs basées sur la densité
  // Utiliser la configuration de densité si density est fourni ou si persistDensity est activé
  // Si persistDensity est activé, on utilise toujours la densité (même si elle vient de localStorage)
  const useDensity = densityProp !== undefined || persistDensity || showDensitySelector;
  const densityConfig = useDensity ? getDensityConfig(currentDensity) : null;
  
  // Si gap est fourni explicitement, l'utiliser, sinon utiliser celui de la densité ou 'md' par défaut
  const effectiveGap = gap !== undefined ? gap : (densityConfig?.gap || 'md');
  // Si cardSize est fourni explicitement, l'utiliser, sinon utiliser celui de la densité ou 'md' par défaut
  const effectiveCardSize = cardSize !== undefined ? cardSize : (densityConfig?.cardSize || 'md');
  // Ajuster les colonnes seulement si on utilise la densité et qu'elle le demande
  const effectiveColumns = densityConfig?.adjustColumns ? Math.min((columns || 4) + 1, 6) : (columns || 4);

  // Déterminer les classes de colonnes
  const gridColsClass = autoColumns
    ? getAutoGridColsClass(mobileColumns)
    : getGridColsClass(effectiveColumns, mobileColumns);
  
  const gapClass = getGapClass(effectiveGap);

  const handleDensityChange = (newDensity: DensityMode) => {
    setDensityState(newDensity);
    onDensityChange?.(newDensity);
  };

  // État de chargement
  if (isLoading) {
    // Créer un skeleton grid
    return (
      <div
        className={cn(
          'grid',
          gapClass,
          gridColsClass,
          className
        )}
      >
        {Array.from({ length: skeletonCount }).map((_, index) => (
          <div
            key={index}
            className="flex flex-col rounded-lg overflow-hidden bg-white dark:bg-gray-800 border border-gray-200 dark:border-gray-700 animate-pulse"
          >
            <div className="aspect-square bg-gray-200 dark:bg-gray-700" />
            <div className="p-3 space-y-2">
              <div className="h-4 bg-gray-200 dark:bg-gray-700 rounded w-3/4" />
              {showMetadata && (
                <div className="h-3 bg-gray-200 dark:bg-gray-700 rounded w-1/2" />
              )}
            </div>
          </div>
        ))}
      </div>
    );
  }

  // État vide
  if (tracks.length === 0) {
    return (
      <TrackListEmpty
        message={emptyMessage}
        description={emptyDescription}
        icon={emptyIcon}
        action={emptyAction}
        className={className}
      />
    );
  }

  return (
    <div className={cn('space-y-4', className)}>
      {showDensitySelector && (
        <div className="flex justify-end">
          <TrackGridDensitySelector
            value={currentDensity}
            onChange={handleDensityChange}
          />
        </div>
      )}
      <div
        className={cn(
          'grid',
          gapClass,
          gridColsClass
        )}
        role="grid"
        aria-label="Grille de pistes"
      >
        {tracks.map((track) => {
          const trackIsLiked = isLiked?.(track.id) ?? false;
          const trackIsPlaying = (isPlaying?.(track.id) ?? false) || currentPlayingId === track.id;

          return (
            <TrackCard
              key={track.id}
              track={track}
              onPlay={onTrackPlay}
              onLike={onTrackLike}
              onMore={onTrackMore}
              onClick={onTrackClick}
              isLiked={trackIsLiked}
              isPlaying={trackIsPlaying}
              showActions={showActions}
              showDuration={showDuration}
              size={effectiveCardSize}
            />
          );
        })}
      </div>
    </div>
  );
}

/**
 * Retourne les classes CSS pour le nombre de colonnes avec responsive
 * Utilise des breakpoints précis : sm (640px), md (768px), lg (1024px), xl (1280px), 2xl (1536px)
 */
function getGridColsClass(columns: 2 | 3 | 4 | 5 | 6, mobileColumns: 1 | 2 = 2): string {
  const mobileClass = mobileColumns === 1 ? 'grid-cols-1' : 'grid-cols-2';
  
  const gridCols = {
    2: `${mobileClass} sm:grid-cols-2`,
    3: `${mobileClass} sm:grid-cols-2 md:grid-cols-3`,
    4: `${mobileClass} sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4`,
    5: `${mobileClass} sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5`,
    6: `${mobileClass} sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6`,
  };

  return gridCols[columns] || gridCols[4];
}

/**
 * Retourne les classes CSS pour des colonnes adaptatives
 * S'adapte automatiquement à la taille d'écran
 */
function getAutoGridColsClass(mobileColumns: 1 | 2 = 2): string {
  const mobileClass = mobileColumns === 1 ? 'grid-cols-1' : 'grid-cols-2';
  // Colonnes adaptatives : 1-2 sur mobile, 2-3 sur tablette, 3-4 sur desktop, 4-6 sur large desktop
  return `${mobileClass} sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 2xl:grid-cols-6`;
}

/**
 * Retourne les classes CSS pour l'espacement entre les cartes
 */
function getGapClass(gap: 'sm' | 'md' | 'lg'): string {
  const gapClasses = {
    sm: 'gap-2 sm:gap-3', // Plus compact sur mobile
    md: 'gap-3 sm:gap-4', // Espacement moyen
    lg: 'gap-4 sm:gap-6', // Plus d'espace
  };

  return gapClasses[gap] || gapClasses.md;
}

/**
 * Retourne la configuration basée sur le mode de densité
 */
function getDensityConfig(density: DensityMode): {
  gap: 'sm' | 'md' | 'lg';
  cardSize: 'sm' | 'md' | 'lg';
  adjustColumns: boolean;
} {
  const configs = {
    compact: {
      gap: 'sm' as const,
      cardSize: 'sm' as const,
      adjustColumns: true, // Plus de colonnes en mode compact
    },
    normal: {
      gap: 'md' as const,
      cardSize: 'md' as const,
      adjustColumns: false,
    },
    comfortable: {
      gap: 'lg' as const,
      cardSize: 'lg' as const,
      adjustColumns: false,
    },
  };

  return configs[density] || configs.normal;
}

export default TrackGrid;

