import { useState, useEffect } from 'react'
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
import { useBreadcrumb } from '../hooks/useBreadcrumb'
import { breadcrumbConfig } from '../config/breadcrumbConfig'
import { api, getErrorMessage } from '../lib/api'
import { notificationManager } from '../lib/notificationManager'
import { formatBytes, formatPlatformName, isVideoFile } from '../lib/utils'
import { invalidateAllFileCaches, optimisticRemoveFromRecycleBin } from '../lib/cacheInvalidation'
import { RotateCcw, Trash2 as TrashIcon, Play, Check, Trash2, Copy } from 'lucide-react'
import EnhancedLightbox from '../components/EnhancedLightbox'
import { FilterBar } from '../components/FilterPopover'
import { BatchProgressModal, BatchProgressItem } from '../components/BatchProgressModal'
import ThrottledImage from '../components/ThrottledImage'
import { CopyToGalleryModal } from '../components/private-gallery/CopyToGalleryModal'
import { useEnabledFeatures } from '../hooks/useEnabledFeatures'

interface RecycleBinItem {
  id: string
  original_path: string
  recycle_path: string
  original_filename: string
  file_extension: string
  file_size: number
  original_mtime: number
  deleted_from: 'downloads' | 'media' | 'review' | 'instagram_perceptual_duplicate_detection'
  deleted_at: string
  deleted_by: string
  metadata: string
  restore_count: number
  width?: number
  height?: number
  platform?: string
  source?: string
  video_id?: string
  face_recognition?: {
    scanned: boolean
    matched: boolean
    matched_person?: string
    confidence?: number
    face_count?: number
  }
}

interface RecycleBinStats {
  total_count: number
  total_size: number
  by_source: {
    [key: string]: {
      count: number
      size: number
    }
  }
}

export default function RecycleBin() {
  useBreadcrumb(breadcrumbConfig['/recycle-bin'])
  const { isFeatureEnabled } = useEnabledFeatures()
  const [filter, setFilter] = useState<string | null>(null)
  const [selectedItems, setSelectedItems] = useState<Set<string>>(new Set())
  const [selectedPaths, setSelectedPaths] = useState<Map<string, { recyclePath: string, originalFilename: string }>>(new Map())
  const [selectMode, setSelectMode] = useState(false)
  const [selectedMedia, setSelectedMedia] = useState<RecycleBinItem | null>(null)
  const [showCopyToGalleryModal, setShowCopyToGalleryModal] = useState(false)
  const [page, setPage] = useState(0)
  const queryClient = useQueryClient()

  // Search and filters
  const [searchQuery, setSearchQuery] = useState<string>('')
  const [platformFilter, setPlatformFilter] = useState<string>('')
  const [sourceFilter, setSourceFilter] = useState<string>('')
  const [typeFilter, setTypeFilter] = useState<'all' | 'image' | 'video'>('all')
  const [sortBy, setSortBy] = useState<string>('download_date')
  const [sortOrder, setSortOrder] = useState<'asc' | 'desc'>('desc')

  // Advanced filters
  const [dateFrom, setDateFrom] = useState<string>('')
  const [dateTo, setDateTo] = useState<string>('')
  const [sizeMin, setSizeMin] = useState<string>('')
  const [sizeMax, setSizeMax] = useState<string>('')

  // Progress modal
  const [showProgressModal, setShowProgressModal] = useState(false)
  const [progressFiles, setProgressFiles] = useState<BatchProgressItem[]>([])
  const [progressTitle, setProgressTitle] = useState('Processing Files')

  const limit = 50

  // Reset page when any filter changes
  useEffect(() => {
    setPage(0)
  }, [filter, platformFilter, sourceFilter, searchQuery, typeFilter, dateFrom, dateTo, sizeMin, sizeMax, sortBy, sortOrder])

  // Fetch recycle bin items
  const { data: recycleBinData, isLoading } = useQuery({
    queryKey: ['recycle-bin', filter, platformFilter, sourceFilter, searchQuery, typeFilter, dateFrom, dateTo, sizeMin, sizeMax, sortBy, sortOrder, page],
    queryFn: async () => {
      const params = new URLSearchParams()
      if (filter) params.append('deleted_from', filter)
      if (platformFilter) params.append('platform', platformFilter)
      if (sourceFilter) params.append('source', sourceFilter)
      if (searchQuery) params.append('search', searchQuery)
      if (typeFilter !== 'all') params.append('media_type', typeFilter)
      if (dateFrom) params.append('date_from', dateFrom)
      if (dateTo) params.append('date_to', dateTo)
      if (sizeMin) params.append('size_min', sizeMin)
      if (sizeMax) params.append('size_max', sizeMax)
      params.append('sort_by', sortBy)
      params.append('sort_order', sortOrder)
      params.append('limit', limit.toString())
      params.append('offset', (page * limit).toString())

      const response: any = await api.get(`/recycle/list?${params}`)
      return response
    },
    refetchInterval: 30000,
  })

  // Fetch filter options
  const { data: filters } = useQuery({
    queryKey: ['recycle-filters', platformFilter],
    queryFn: () => api.getRecycleFilters(platformFilter || undefined),
  })

  // Clear source filter when platform changes and source is not available
  useEffect(() => {
    if (filters && sourceFilter && !filters.sources.includes(sourceFilter)) {
      setSourceFilter('')
    }
  }, [filters, sourceFilter])

  // Fetch stats
  const { data: statsData } = useQuery({
    queryKey: ['recycle-bin-stats'],
    queryFn: async () => {
      const response: any = await api.get('/recycle/stats')
      return response
    },
    refetchInterval: 30000,
  })

  const items: RecycleBinItem[] = recycleBinData?.items || []
  const filteredTotal = recycleBinData?.total || 0  // Total count for current filter
  const stats: RecycleBinStats = statsData?.stats || { total_count: 0, total_size: 0, by_source: {} }

  // Items are now filtered and sorted server-side
  const filteredItems = items

  const totalPages = Math.ceil(filteredTotal / limit)

  // Check if any client-side filters are active
  const hasActiveFilters = searchQuery || typeFilter !== 'all' || platformFilter || sourceFilter || dateFrom || dateTo || sizeMin || sizeMax

  // Fetch metadata for current lightbox item when it changes
  useEffect(() => {
    if (!selectedMedia?.id) return
    // Skip if already has dimensions
    if (selectedMedia.width && selectedMedia.height) return

    const fetchMetadata = async () => {
      try {
        const response = await api.get(`/recycle/metadata/${selectedMedia.id}`) as any
        if (response && (response.width || response.height || response.platform || response.source)) {
          setSelectedMedia((prev: any) => prev?.id === selectedMedia.id ? {
            ...prev,
            width: response.width,
            height: response.height,
            platform: response.platform || prev.platform,
            source: response.source || prev.source
          } : prev)
        }
      } catch (error) {
        // Silently fail - dimensions are optional
      }
    }
    fetchMetadata()
  }, [selectedMedia?.id])

  // Helper function to advance to next/previous item after delete/restore
  const advanceToNextItem = () => {
    if (!selectedMedia) return

    const currentIndex = filteredItems.findIndex(item => item.id === selectedMedia.id)
    if (currentIndex === -1) {
      setSelectedMedia(null)
      return
    }

    // Try next item first
    if (currentIndex + 1 < filteredItems.length) {
      setSelectedMedia(filteredItems[currentIndex + 1])
    }
    // If no next item, try previous
    else if (currentIndex - 1 >= 0) {
      setSelectedMedia(filteredItems[currentIndex - 1])
    }
    // If no items left, close lightbox
    else {
      setSelectedMedia(null)
    }
  }

  // Restore mutation
  const restoreMutation = useMutation({
    mutationFn: (id: string) => api.post('/recycle/restore', { recycle_id: id }),
    onSuccess: (_data, variables) => {
      // Advance to next item before invalidating queries
      advanceToNextItem()
      optimisticRemoveFromRecycleBin(queryClient, new Set([variables]))
      invalidateAllFileCaches(queryClient)
      notificationManager.success('Restored', 'File restored successfully')
      // Trigger Immich scan (don't await - fire and forget)
      api.triggerImmichScan().catch(() => {})
    },
    onError: (err: unknown) => {
      notificationManager.apiError('Restore Failed', err, 'Failed to restore file')
    },
  })

  // Delete mutation
  const deleteMutation = useMutation({
    mutationFn: (id: string) => api.delete(`/recycle/delete/${id}`),
    onSuccess: (_data, variables) => {
      // Advance to next item before invalidating queries
      advanceToNextItem()
      optimisticRemoveFromRecycleBin(queryClient, new Set([variables]))
      invalidateAllFileCaches(queryClient)
      notificationManager.deleted('File', 'File permanently deleted')
    },
    onError: (err: unknown) => {
      notificationManager.deleteError('file', err)
    },
  })

  // Batch restore
  const handleBatchRestore = async () => {
    const selectedIds = Array.from(selectedItems)

    // Build progress items from selected IDs
    const progressItems: BatchProgressItem[] = selectedIds.map(id => {
      const item = items.find((i: RecycleBinItem) => i.id === id)
      return {
        id,
        filename: item?.original_filename || id,
        status: 'pending' as const
      }
    })

    setProgressFiles(progressItems)
    setProgressTitle('Restoring Files')
    setShowProgressModal(true)

    let succeeded = 0
    let failed = 0

    for (const id of selectedIds) {
      // Mark as processing
      setProgressFiles(prev => prev.map(f =>
        f.id === id ? { ...f, status: 'processing' } : f
      ))

      try {
        await api.post('/recycle/restore', { recycle_id: id })
        succeeded++
        setProgressFiles(prev => prev.map(f =>
          f.id === id ? { ...f, status: 'success' } : f
        ))
      } catch (err: unknown) {
        failed++
        setProgressFiles(prev => prev.map(f =>
          f.id === id ? { ...f, status: 'error', error: getErrorMessage(err) } : f
        ))
      }
    }

    optimisticRemoveFromRecycleBin(queryClient, new Set(selectedIds))
    invalidateAllFileCaches(queryClient)
    setSelectedItems(new Set())
    setSelectedPaths(new Map())
    setSelectMode(false)

    setTimeout(() => {
      setShowProgressModal(false)
      notificationManager.batchSuccess('Restore', succeeded, 'file')
    }, 1500)
  }

  // Batch delete
  const handleBatchDelete = async () => {
    if (!confirm(`Permanently delete ${selectedItems.size} file(s)? This cannot be undone!`)) return

    const selectedIds = Array.from(selectedItems)

    // Build progress items from selected IDs
    const progressItems: BatchProgressItem[] = selectedIds.map(id => {
      const item = items.find((i: RecycleBinItem) => i.id === id)
      return {
        id,
        filename: item?.original_filename || id,
        status: 'pending' as const
      }
    })

    setProgressFiles(progressItems)
    setProgressTitle('Permanently Deleting Files')
    setShowProgressModal(true)

    let succeeded = 0
    let failed = 0

    for (const id of selectedIds) {
      // Mark as processing
      setProgressFiles(prev => prev.map(f =>
        f.id === id ? { ...f, status: 'processing' } : f
      ))

      try {
        await api.delete(`/recycle/delete/${id}`)
        succeeded++
        setProgressFiles(prev => prev.map(f =>
          f.id === id ? { ...f, status: 'success' } : f
        ))
      } catch (err: unknown) {
        failed++
        setProgressFiles(prev => prev.map(f =>
          f.id === id ? { ...f, status: 'error', error: getErrorMessage(err) } : f
        ))
      }
    }

    optimisticRemoveFromRecycleBin(queryClient, new Set(selectedIds))
    invalidateAllFileCaches(queryClient)
    setSelectedItems(new Set())
    setSelectedPaths(new Map())
    setSelectMode(false)

    setTimeout(() => {
      setShowProgressModal(false)
      notificationManager.batchSuccess('Delete', succeeded, 'file')
    }, 1500)
  }

  // Empty all
  const handleEmptyAll = async () => {
    if (!confirm(`Permanently delete ALL ${stats.total_count} file(s) in recycle bin? This cannot be undone!`)) return

    // Show progress for all items
    const progressItems: BatchProgressItem[] = items.map((item: RecycleBinItem) => ({
      id: item.id,
      filename: item.original_filename,
      status: 'processing' as const
    }))

    setProgressFiles(progressItems)
    setProgressTitle('Emptying Recycle Bin')
    setShowProgressModal(true)

    try {
      const result = await api.post('/recycle/empty', { older_than_days: undefined })
      const deletedCount = (result as any)?.deleted_count || items.length

      // Mark all as success
      setProgressFiles(prev => prev.map(f => ({ ...f, status: 'success' as const })))

      optimisticRemoveFromRecycleBin(queryClient, new Set(items.map((item: RecycleBinItem) => item.id)))
      invalidateAllFileCaches(queryClient)

      setTimeout(() => {
        setShowProgressModal(false)
        notificationManager.batchSuccess('Delete', deletedCount, 'file')
      }, 1500)
    } catch (err) {
      setShowProgressModal(false)
      notificationManager.batchError('Empty Recycle Bin', err)
    }
  }

  // Get media thumbnail URL for recycle bin items
  const getRecycleThumbnailUrl = (item: RecycleBinItem) => {
    // For YouTube videos with video_id, use stored thumbnail from video_downloads
    if (item.platform === 'youtube' && item.video_id) {
      return `/api/video/thumbnail/${item.platform}/${item.video_id}?source=downloads`
    }
    const mediaType = isVideoFile(item.original_filename) ? 'video' : 'image'
    // Security: Auth via httpOnly cookie only - no token in URL
    return `/api/recycle/file/${item.id}?thumbnail=true&type=${mediaType}`
  }

  const getRecyclePreviewUrl = (recycleId: string) => {
    // Security: Auth via httpOnly cookie only - no token in URL
    return `/api/recycle/file/${recycleId}`
  }

  // Toggle select mode
  const toggleSelectMode = () => {
    setSelectMode(!selectMode)
    setSelectedItems(new Set())
    setSelectedPaths(new Map())
  }

  // Toggle item selection
  const toggleItem = (id: string) => {
    const newSet = new Set(selectedItems)
    const newPaths = new Map(selectedPaths)
    if (newSet.has(id)) {
      newSet.delete(id)
      newPaths.delete(id)
    } else {
      newSet.add(id)
      const item = filteredItems.find(i => i.id === id)
      if (item) newPaths.set(id, { recyclePath: item.recycle_path, originalFilename: item.original_filename })
    }
    setSelectedItems(newSet)
    setSelectedPaths(newPaths)
  }

  // Select all
  const selectAll = () => {
    if (selectedItems.size === filteredItems.length) {
      setSelectedItems(new Set())
      setSelectedPaths(new Map())
    } else {
      setSelectedItems(new Set(filteredItems.map(item => item.id)))
      setSelectedPaths(new Map(filteredItems.map(item => [item.id, { recyclePath: item.recycle_path, originalFilename: item.original_filename }])))
    }
  }

  // Helper to get current index for lightbox
  const getCurrentLightboxIndex = () => {
    if (!selectedMedia) return -1
    return filteredItems.findIndex((item) => item.id === selectedMedia.id)
  }

  // Get items for lightbox - use selectedMedia for current item (has fetched metadata)
  const getLightboxItems = () => {
    if (!selectedMedia) return filteredItems
    return filteredItems.map(item =>
      item.id === selectedMedia.id ? selectedMedia : item
    )
  }

  return (
    <div className="space-y-6">
      {/* Header */}
      <div>
        <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4 mb-2">
          <div>
            <h1 className="text-2xl sm:text-3xl font-bold flex items-center gap-2 sm:gap-3">
              <Trash2 className="w-8 h-8 text-red-500" />
              Recycle Bin
            </h1>
            <p className="text-slate-600 dark:text-slate-400 mt-1">
              Restore or permanently delete removed files
            </p>
          </div>
          <div className="flex flex-wrap gap-3">
            <button
              onClick={toggleSelectMode}
              className="px-4 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 min-h-[44px] transition-colors"
            >
              {selectMode ? 'Cancel Selection' : 'Select Multiple'}
            </button>
            <button
              onClick={handleEmptyAll}
              disabled={stats.total_count === 0}
              className="px-4 py-2.5 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed min-h-[44px] transition-colors"
            >
              Empty Recycle Bin
            </button>
          </div>
        </div>
      </div>

      {/* Stats */}
      <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
        <div className="card-glass-hover rounded-xl p-4">
          <div className="text-sm text-muted-foreground">Total Files</div>
          <div className="text-2xl font-bold text-foreground animate-count-up">{stats.total_count}</div>
        </div>
        <div className="card-glass-hover rounded-xl p-4">
          <div className="text-sm text-muted-foreground">Total Size</div>
          <div className="text-2xl font-bold text-foreground animate-count-up">{formatBytes(stats.total_size)}</div>
        </div>
        <div className="card-glass-hover rounded-xl p-4">
          <div className="text-sm text-muted-foreground">From Media</div>
          <div className="text-2xl font-bold text-foreground animate-count-up">
            {stats.by_source.media?.count || 0}
          </div>
        </div>
        <div className="card-glass-hover rounded-xl p-4">
          <div className="text-sm text-muted-foreground">From Review</div>
          <div className="text-2xl font-bold text-foreground animate-count-up">
            {stats.by_source.review?.count || 0}
          </div>
        </div>
      </div>

      {/* Filters */}
      <div className="card-glass-hover rounded-xl p-4 relative z-30">
        <FilterBar
          searchValue={searchQuery}
          onSearchChange={setSearchQuery}
          searchPlaceholder="Search filenames..."
          filterSections={[
            {
              id: 'type',
              label: 'Media Type',
              type: 'select',
              options: [
                { value: 'all', label: 'All Media' },
                { value: 'image', label: 'Images Only' },
                { value: 'video', label: 'Videos Only' },
              ],
              value: typeFilter,
              onChange: (v) => setTypeFilter(v as 'all' | 'image' | 'video'),
            },
            {
              id: 'deletedFrom',
              label: 'Deleted From',
              type: 'select',
              options: [
                { value: '', label: `All Deleted From (${stats.total_count})` },
                { value: 'downloads', label: `Downloads (${stats.by_source.downloads?.count || 0})` },
                { value: 'media', label: `Media (${stats.by_source.media?.count || 0})` },
                { value: 'review', label: `Review (${stats.by_source.review?.count || 0})` },
                { value: 'instagram_perceptual_duplicate_detection', label: `Perceptual Duplicates (${stats.by_source.instagram_perceptual_duplicate_detection?.count || 0})` },
              ],
              value: filter || '',
              onChange: (v) => setFilter(v as string || null),
            },
            {
              id: 'platform',
              label: 'Platform',
              type: 'select',
              options: [
                { value: '', label: 'All Platforms' },
                ...(filters?.platforms.map((platform) => ({
                  value: platform,
                  label: formatPlatformName(platform),
                })) || []),
              ],
              value: platformFilter,
              onChange: (v) => { setPlatformFilter(v as string); setPage(0) },
            },
            {
              id: 'source',
              label: 'Source',
              type: 'select',
              options: [
                { value: '', label: 'All Sources' },
                ...(filters?.sources.map((source) => ({
                  value: source,
                  label: source,
                })) || []),
              ],
              value: sourceFilter,
              onChange: (v) => { setSourceFilter(v as string); setPage(0) },
            },
            {
              id: 'sortBy',
              label: 'Sort By',
              type: 'select',
              options: [
                { value: 'download_date', label: 'Download Date' },
                { value: 'post_date', label: 'Post Date' },
                { value: 'deleted_at', label: 'Deleted Date' },
                { value: 'file_size', label: 'File Size' },
                { value: 'filename', label: 'Filename' },
                { value: 'deleted_from', label: 'Source' },
                { value: 'confidence', label: 'Face Confidence' },
              ],
              value: sortBy,
              onChange: (v) => setSortBy(v as string),
            },
            {
              id: 'sortOrder',
              label: 'Sort Order',
              type: 'select',
              options: [
                { value: 'desc', label: 'Newest First' },
                { value: 'asc', label: 'Oldest First' },
              ],
              value: sortOrder,
              onChange: (v) => setSortOrder(v as 'asc' | 'desc'),
            },
          ]}
          activeFilters={[
            ...(typeFilter !== 'all' ? [{
              id: 'type',
              label: 'Type',
              value: typeFilter,
              displayValue: typeFilter === 'image' ? 'Images' : 'Videos',
              onRemove: () => setTypeFilter('all'),
            }] : []),
            ...(filter ? [{
              id: 'deletedFrom',
              label: 'Deleted From',
              value: filter,
              displayValue: filter === 'instagram_perceptual_duplicate_detection' ? 'Perceptual Duplicates' : filter.charAt(0).toUpperCase() + filter.slice(1),
              onRemove: () => setFilter(null),
            }] : []),
            ...(platformFilter ? [{
              id: 'platform',
              label: 'Platform',
              value: platformFilter,
              displayValue: formatPlatformName(platformFilter),
              onRemove: () => { setPlatformFilter(''); setPage(0) },
            }] : []),
            ...(sourceFilter ? [{
              id: 'source',
              label: 'Source',
              value: sourceFilter,
              displayValue: sourceFilter,
              onRemove: () => { setSourceFilter(''); setPage(0) },
            }] : []),
            ...(searchQuery ? [{
              id: 'search',
              label: 'Search',
              value: searchQuery,
              displayValue: `"${searchQuery}"`,
              onRemove: () => setSearchQuery(''),
            }] : []),
            ...(dateFrom ? [{
              id: 'dateFrom',
              label: 'From',
              value: dateFrom,
              displayValue: dateFrom,
              onRemove: () => setDateFrom(''),
            }] : []),
            ...(dateTo ? [{
              id: 'dateTo',
              label: 'To',
              value: dateTo,
              displayValue: dateTo,
              onRemove: () => setDateTo(''),
            }] : []),
            ...(sizeMin ? [{
              id: 'sizeMin',
              label: 'Min Size',
              value: sizeMin,
              displayValue: `${sizeMin} bytes`,
              onRemove: () => setSizeMin(''),
            }] : []),
            ...(sizeMax ? [{
              id: 'sizeMax',
              label: 'Max Size',
              value: sizeMax,
              displayValue: `${sizeMax} bytes`,
              onRemove: () => setSizeMax(''),
            }] : []),
          ]}
          onClearAll={() => {
            setTypeFilter('all')
            setSearchQuery('')
            setFilter(null)
            setPlatformFilter('')
            setSourceFilter('')
            setDateFrom('')
            setDateTo('')
            setSizeMin('')
            setSizeMax('')
          }}
          advancedFilters={{
            dateFrom: { value: dateFrom, onChange: setDateFrom, label: 'Deleted From' },
            dateTo: { value: dateTo, onChange: setDateTo, label: 'Deleted To' },
            sizeMin: { value: sizeMin, onChange: setSizeMin, placeholder: '1MB = 1048576' },
            sizeMax: { value: sizeMax, onChange: setSizeMax, placeholder: '10MB = 10485760' },
          }}
          totalCount={filteredTotal}
          countLabel="items"
        />
      </div>

      {/* Stats showing filtered count */}
      <div className="flex items-center justify-between text-sm text-slate-600 dark:text-slate-400">
        <div>
          {hasActiveFilters ? (
            <>Showing {filteredItems.length} of {filteredTotal} filtered items</>
          ) : (
            <>Showing {filteredItems.length} of {filteredTotal} items</>
          )}
        </div>
        {totalPages > 1 && (
          <div>
            Page {page + 1} of {totalPages}
          </div>
        )}
      </div>

      {/* Selection Bar */}
      {selectMode && filteredItems.length > 0 && (
        <div className="bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800 rounded-lg p-4">
          <div className="flex flex-col md:flex-row md:items-center justify-between gap-4">
            <div className="flex flex-wrap items-center gap-3">
              <button
                onClick={selectAll}
                className="flex items-center space-x-2 px-3 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg hover:bg-slate-50 dark:hover:bg-slate-700 text-sm min-h-[44px] transition-colors"
              >
                {selectedItems.size === filteredItems.length ? (
                  <Check className="w-5 h-5" />
                ) : (
                  <span className="w-5 h-5 border-2 border-slate-400 rounded" />
                )}
                <span>{selectedItems.size === filteredItems.length ? 'Deselect All' : 'Select All'}</span>
              </button>
              <span className="text-sm text-blue-700 dark:text-blue-400">
                {selectedItems.size} item{selectedItems.size !== 1 ? 's' : ''} selected
              </span>
            </div>
            <div className="flex flex-wrap items-center gap-2">
              <button
                onClick={handleBatchRestore}
                disabled={selectedItems.size === 0}
                className="flex items-center space-x-2 px-3 py-2 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 disabled:cursor-not-allowed min-h-[44px] text-sm transition-colors"
              >
                <RotateCcw className="w-5 h-5" />
                <span className="hidden sm:inline">Restore Selected</span>
                <span className="sm:hidden">Restore</span>
              </button>
              {isFeatureEnabled('/private-gallery') && (
              <button
                onClick={() => setShowCopyToGalleryModal(true)}
                disabled={selectedItems.size === 0}
                className="flex items-center space-x-2 px-3 py-2 bg-violet-600 text-white rounded-lg hover:bg-violet-700 disabled:opacity-50 disabled:cursor-not-allowed min-h-[44px] text-sm transition-colors"
              >
                <Copy className="w-4 h-4" />
                <span className="hidden sm:inline">Copy to Private</span>
                <span className="sm:hidden">Private</span>
              </button>
              )}
              <button
                onClick={handleBatchDelete}
                disabled={selectedItems.size === 0}
                className="flex items-center space-x-2 px-3 py-2 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50 disabled:cursor-not-allowed min-h-[44px] text-sm transition-colors"
              >
                <TrashIcon className="w-5 h-5" />
                <span className="hidden sm:inline">Delete Forever</span>
                <span className="sm:hidden">Delete</span>
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Gallery Grid */}
      {isLoading ? (
        <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4">
          {[...Array(20)].map((_, i) => (
            <div key={i} className="aspect-square bg-slate-200 dark:bg-slate-800 rounded-lg animate-pulse" />
          ))}
        </div>
      ) : filteredItems.length === 0 ? (
        <div className="text-center py-20">
          <p className="text-slate-500 dark:text-slate-400 text-lg">
            {items.length === 0 ? 'Recycle bin is empty' : 'No items match the current filters'}
          </p>
        </div>
      ) : (
        <div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-5 gap-4">
              {filteredItems.map((item) => {
                const isVideo = isVideoFile(item.original_filename)

                return (
                  <div
                    key={item.id}
                    onClick={() => selectMode ? toggleItem(item.id) : setSelectedMedia(item)}
                    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 ${
                      selectedItems.has(item.id)
                        ? 'ring-2 ring-blue-500'
                        : 'hover:ring-blue-500'
                    }`}
                  >
                    {/* Thumbnail - show for all files since we support image and video */}
                    {item.original_filename ? (
                      <ThrottledImage
                        src={getRecycleThumbnailUrl(item)}
                        alt={item.original_filename}
                        className="w-full h-full object-cover"
                      />
                    ) : (
                      <div className="w-full h-full flex items-center justify-center">
                        <TrashIcon className="w-12 h-12 text-gray-400 dark:text-gray-500" />
                      </div>
                    )}

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

                    {/* Face recognition badge */}
                    {item.face_recognition?.scanned && (
                      <div className={`absolute ${selectMode ? 'top-10' : 'top-2'} left-2 px-1.5 py-0.5 text-white text-xs font-medium rounded z-10 ${
                        item.face_recognition.matched
                          ? (item.face_recognition.confidence ?? 0) >= 0.8
                            ? 'bg-green-600'
                            : (item.face_recognition.confidence ?? 0) >= 0.5
                              ? 'bg-yellow-600'
                              : 'bg-orange-600'
                          : item.face_recognition.confidence && item.face_recognition.confidence > 0
                            ? 'bg-red-600'
                            : 'bg-gray-500'
                      }`}>
                        {item.face_recognition.confidence && item.face_recognition.confidence > 0 ? (
                          <>{Math.round(item.face_recognition.confidence * 100)}%</>
                        ) : (
                          'No Match'
                        )}
                      </div>
                    )}

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

                    {/* Hover overlay with actions */}
                    {!selectMode && (
                      <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">
                        <button
                          onClick={(e) => {
                            e.stopPropagation()
                            restoreMutation.mutate(item.id)
                          }}
                          className="w-full px-3 py-2.5 bg-green-600 text-white rounded-lg hover:bg-green-700 disabled:opacity-50 flex items-center justify-center space-x-2 text-sm min-h-[44px] transition-colors"
                        >
                          <RotateCcw className="w-4 h-4" />
                          <span>Restore</span>
                        </button>
                        <button
                          onClick={(e) => {
                            e.stopPropagation()
                            if (confirm(`Permanently delete ${item.original_filename}? This cannot be undone!`)) {
                              deleteMutation.mutate(item.id)
                            }
                          }}
                          className="w-full px-3 py-2.5 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50 flex items-center justify-center space-x-2 text-sm min-h-[44px] transition-colors"
                        >
                          <TrashIcon className="w-4 h-4" />
                          <span>Delete</span>
                        </button>
                      </div>
                    )}

                    {/* Info overlay 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">{item.original_filename}</p>
                        <div className="flex items-center justify-between text-white/70 text-xs mt-1">
                          <span>{formatBytes(item.file_size)}</span>
                          <span className={`px-1.5 py-0.5 rounded text-[10px] font-medium ${
                            item.deleted_from === 'media' ? 'bg-blue-600' :
                            item.deleted_from === 'review' ? 'bg-yellow-600' :
                            item.deleted_from === 'instagram_perceptual_duplicate_detection' ? 'bg-red-600' :
                            'bg-purple-600'
                          }`}>
                            {item.deleted_from === 'instagram_perceptual_duplicate_detection' ? 'Duplicate' :
                             item.deleted_from.charAt(0).toUpperCase() + item.deleted_from.slice(1)}
                          </span>
                        </div>
                      </div>
                    )}
                  </div>
                )
              })}
        </div>
      )}

      {/* Pagination */}
      {totalPages > 1 && (
        <div className="flex justify-center space-x-2">
          <button
            onClick={() => setPage((p) => Math.max(0, p - 1))}
            disabled={page === 0}
            className="px-4 py-2.5 border border-slate-300 dark:border-slate-600 rounded-lg disabled:opacity-50 hover:bg-slate-50 dark:hover:bg-slate-800 min-h-[44px] transition-colors"
          >
            Previous
          </button>
          <span className="px-4 py-2 text-slate-600 dark:text-slate-400">
            {page + 1} / {totalPages}
          </span>
          <button
            onClick={() => setPage((p) => Math.min(totalPages - 1, p + 1))}
            disabled={page >= totalPages - 1}
            className="px-4 py-2.5 border border-slate-300 dark:border-slate-600 rounded-lg disabled:opacity-50 hover:bg-slate-50 dark:hover:bg-slate-800 min-h-[44px] transition-colors"
          >
            Next
          </button>
        </div>
      )}

      {/* Lightbox */}
      {selectedMedia && getCurrentLightboxIndex() >= 0 && (
        <EnhancedLightbox
          items={getLightboxItems()}
          currentIndex={getCurrentLightboxIndex()}
          onClose={() => setSelectedMedia(null)}
          onNavigate={(index) => setSelectedMedia(filteredItems[index])}
          onDelete={(item) => {
            if (confirm(`Permanently delete ${item.original_filename}? This cannot be undone!`)) {
              deleteMutation.mutate(item.id)
            }
          }}
          getPreviewUrl={(item) => getRecyclePreviewUrl(item.id)}
          getThumbnailUrl={(item: RecycleBinItem) => getRecycleThumbnailUrl(item)}
          isVideo={(item) => isVideoFile(item.original_filename)}
          renderActions={(item) => (
            <>
              <button
                onClick={() => restoreMutation.mutate(item.id)}
                disabled={restoreMutation.isPending}
                className="flex-1 flex items-center justify-center gap-1.5 md:gap-2 px-3 py-1.5 md:px-4 md:py-3 bg-green-600 hover:bg-green-700 disabled:bg-green-800 disabled:opacity-50 text-white text-sm md:text-base rounded-lg transition-colors whitespace-nowrap"
              >
                <RotateCcw className="w-4 h-4 md:w-5 md:h-5" />
                <span>{restoreMutation.isPending ? 'Restoring...' : 'Restore File'}</span>
              </button>
              <button
                onClick={() => {
                  if (confirm(`Permanently delete ${item.original_filename}? This cannot be undone!`)) {
                    deleteMutation.mutate(item.id)
                  }
                }}
                disabled={deleteMutation.isPending}
                className="flex-1 flex items-center justify-center gap-1.5 md:gap-2 px-3 py-1.5 md:px-4 md:py-3 bg-red-600 hover:bg-red-700 disabled:bg-red-800 disabled:opacity-50 text-white text-sm md:text-base rounded-lg transition-colors whitespace-nowrap"
              >
                <TrashIcon className="w-4 h-4 md:w-5 md:h-5" />
                <span>{deleteMutation.isPending ? 'Deleting...' : 'Delete Forever'}</span>
              </button>
            </>
          )}
        />
      )}

      {/* Progress Modal */}
      <BatchProgressModal
        isOpen={showProgressModal}
        title={progressTitle}
        items={progressFiles}
        onClose={() => setShowProgressModal(false)}
      />

      {/* Copy to Private Gallery Modal */}
      <CopyToGalleryModal
        open={showCopyToGalleryModal}
        onClose={() => setShowCopyToGalleryModal(false)}
        sourcePaths={Array.from(selectedPaths.values()).map(v => v.recyclePath)}
        sourceType="recycle"
        sourceNames={Object.fromEntries(
          Array.from(selectedPaths.values()).map(v => [v.recyclePath, v.originalFilename])
        )}
        onSuccess={() => {
          setShowCopyToGalleryModal(false)
          setSelectedItems(new Set())
          setSelectedPaths(new Map())
          setSelectMode(false)
        }}
      />
    </div>
  )
}
