import { memo, ReactNode } from 'react'
import { Play, Check } from 'lucide-react'
import { formatBytes, isVideoFile } from '../lib/utils'
import ThrottledImage from './ThrottledImage'

export interface MediaItem {
  id: string | number
  file_path?: string
  filename?: string
  original_filename?: string
  file_size?: number
  thumbnail_url?: string
}

export interface MediaGridProps<T extends MediaItem> {
  items: T[]
  isLoading?: boolean
  emptyMessage?: string
  emptySubMessage?: string
  selectMode?: boolean
  selectedItems?: Set<string>
  onSelectItem?: (id: string) => void
  onItemClick?: (item: T) => void
  getThumbnailUrl: (item: T) => string
  getItemId: (item: T) => string
  getFilename: (item: T) => string
  renderHoverOverlay?: (item: T) => ReactNode
  renderBadge?: (item: T) => ReactNode
  skeletonCount?: number
  columns?: {
    default: number
    md: number
    lg: number
    xl: number
  }
}

function MediaGridSkeleton({ count = 20, columns }: { count?: number; columns?: MediaGridProps<MediaItem>['columns'] }) {
  const gridCols = columns || { default: 2, md: 3, lg: 4, xl: 5 }

  return (
    <div className={`grid grid-cols-${gridCols.default} md:grid-cols-${gridCols.md} lg:grid-cols-${gridCols.lg} xl:grid-cols-${gridCols.xl} gap-4`}>
      {[...Array(count)].map((_, i) => (
        <div key={i} className="aspect-square bg-slate-200 dark:bg-slate-800 rounded-lg animate-pulse" />
      ))}
    </div>
  )
}

function MediaGridEmpty({ message, subMessage }: { message: string; subMessage?: string }) {
  return (
    <div className="text-center py-20">
      <p className="text-slate-500 dark:text-slate-400 text-lg">{message}</p>
      {subMessage && (
        <p className="text-slate-400 dark:text-slate-500 text-sm mt-2">{subMessage}</p>
      )}
    </div>
  )
}

function MediaGridItemComponent<T extends MediaItem>({
  item,
  selectMode,
  isSelected,
  onSelect,
  onClick,
  getThumbnailUrl,
  getFilename,
  renderHoverOverlay,
  renderBadge,
}: {
  item: T
  selectMode?: boolean
  isSelected: boolean
  onSelect?: () => void
  onClick?: () => void
  getThumbnailUrl: (item: T) => string
  getFilename: (item: T) => string
  renderHoverOverlay?: (item: T) => ReactNode
  renderBadge?: (item: T) => ReactNode
}) {
  const filename = getFilename(item)
  const isVideo = isVideoFile(filename)

  const handleClick = () => {
    if (selectMode && onSelect) {
      onSelect()
    } else if (onClick) {
      onClick()
    }
  }

  return (
    <div
      onClick={handleClick}
      className={`group relative aspect-square bg-slate-100 dark:bg-slate-800 rounded-lg overflow-hidden cursor-pointer hover:ring-2 card-lift thumbnail-zoom ${
        isSelected ? 'ring-2 ring-blue-500' : 'hover:ring-blue-500'
      }`}
    >
      {/* Thumbnail */}
      <ThrottledImage
        src={getThumbnailUrl(item)}
        alt={filename}
        className="w-full h-full object-cover"
      />

      {/* Video indicator */}
      {isVideo && (
        <div className="absolute top-2 right-2 bg-black/70 rounded-full p-1.5 z-10">
          <Play className="w-4 h-4 text-white fill-white" />
        </div>
      )}

      {/* Custom badge (e.g., face recognition confidence) */}
      {renderBadge && (
        <div className={`absolute ${selectMode ? 'top-10' : 'top-2'} left-2 z-10`}>
          {renderBadge(item)}
        </div>
      )}

      {/* Select checkbox */}
      {selectMode && (
        <div className="absolute top-2 left-2 z-20">
          <div className={`w-6 h-6 rounded border-2 flex items-center justify-center transition-colors ${
            isSelected
              ? 'bg-blue-600 border-blue-600'
              : 'bg-white/90 border-slate-300'
          }`}>
            {isSelected && (
              <Check className="w-4 h-4 text-white" />
            )}
          </div>
        </div>
      )}

      {/* Hover overlay with actions */}
      {!selectMode && renderHoverOverlay && (
        <div className="absolute inset-0 bg-black/60 opacity-0 group-hover:opacity-100 transition-opacity flex flex-col items-center justify-center space-y-2 p-2">
          {renderHoverOverlay(item)}
        </div>
      )}

      {/* File info at bottom - only show on hover when not in select mode */}
      {!selectMode && (
        <div className="absolute bottom-0 left-0 right-0 bg-gradient-to-t from-black/80 to-transparent p-2 opacity-0 group-hover:opacity-100 transition-opacity">
          <p className="text-white text-xs truncate">{filename}</p>
          {item.file_size && (
            <p className="text-white/70 text-xs">{formatBytes(item.file_size)}</p>
          )}
        </div>
      )}
    </div>
  )
}

// Memoize the item component
const MediaGridItem = memo(MediaGridItemComponent) as typeof MediaGridItemComponent

export default function MediaGrid<T extends MediaItem>({
  items,
  isLoading = false,
  emptyMessage = 'No items found',
  emptySubMessage,
  selectMode = false,
  selectedItems = new Set(),
  onSelectItem,
  onItemClick,
  getThumbnailUrl,
  getItemId,
  getFilename,
  renderHoverOverlay,
  renderBadge,
  skeletonCount = 20,
  columns = { default: 2, md: 3, lg: 4, xl: 5 },
}: MediaGridProps<T>) {
  if (isLoading) {
    return <MediaGridSkeleton count={skeletonCount} columns={columns} />
  }

  if (items.length === 0) {
    return <MediaGridEmpty message={emptyMessage} subMessage={emptySubMessage} />
  }

  return (
    <div className={`grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4`}>
      {items.map((item) => {
        const itemId = getItemId(item)
        return (
          <MediaGridItem
            key={itemId}
            item={item}
            selectMode={selectMode}
            isSelected={selectedItems.has(itemId)}
            onSelect={onSelectItem ? () => onSelectItem(itemId) : undefined}
            onClick={onItemClick ? () => onItemClick(item) : undefined}
            getThumbnailUrl={getThumbnailUrl}
            getFilename={getFilename}
            renderHoverOverlay={renderHoverOverlay}
            renderBadge={renderBadge}
          />
        )
      })}
    </div>
  )
}

// Re-export for convenience
export { MediaGridSkeleton, MediaGridEmpty }
