import { useState, useEffect, useRef, useCallback } from 'react'
import { useQuery, useMutation } from '@tanstack/react-query'
import { useBreadcrumb } from '../hooks/useBreadcrumb'
import { breadcrumbConfig } from '../config/breadcrumbConfig'
import { Download, Youtube, CheckCircle, XCircle, Clock, Loader2, Info, Trash2, Video, Search, Upload, HardDrive, Play, Pause, List, ChevronDown, ChevronUp, X, Square, CheckSquare, Image, Folder, Clapperboard, ChevronLeft, ChevronRight } from 'lucide-react'
import { api } from '../lib/api'
import { formatBytes, formatDate } from '../lib/utils'
import EnhancedLightbox from '../components/EnhancedLightbox'

// Platform configurations for display (yt-dlp video sites)
const PLATFORMS: Record<string, { name: string; icon: any; color: string }> = {
  youtube: { name: 'YouTube', icon: Youtube, color: 'text-red-500' },
  vimeo: { name: 'Vimeo', icon: Video, color: 'text-blue-500' },
  dailymotion: { name: 'Dailymotion', icon: Video, color: 'text-cyan-500' },
  bilibili: { name: 'Bilibili', icon: Video, color: 'text-pink-500' },
  twitter: { name: 'Twitter/X', icon: Video, color: 'text-sky-500' },
  tiktok: { name: 'TikTok', icon: Video, color: 'text-gray-900 dark:text-white' },
  twitch: { name: 'Twitch', icon: Video, color: 'text-purple-500' },
  instagram: { name: 'Instagram', icon: Video, color: 'text-pink-600' },
  facebook: { name: 'Facebook', icon: Video, color: 'text-blue-600' },
  reddit: { name: 'Reddit', icon: Video, color: 'text-orange-500' },
  // Gallery-dl sites (image/gallery focused)
  erome: { name: 'Erome', icon: Folder, color: 'text-purple-500' },
  bunkr: { name: 'Bunkr', icon: Folder, color: 'text-blue-500' },
  cyberdrop: { name: 'Cyberdrop', icon: Folder, color: 'text-cyan-500' },
  kemono: { name: 'Kemono', icon: Image, color: 'text-green-500' },
  coomer: { name: 'Coomer', icon: Image, color: 'text-pink-500' },
  pixeldrain: { name: 'Pixeldrain', icon: Folder, color: 'text-indigo-500' },
  gofile: { name: 'GoFile', icon: Folder, color: 'text-yellow-500' },
  imgbox: { name: 'ImgBox', icon: Image, color: 'text-gray-500' },
  imagebam: { name: 'ImageBam', icon: Image, color: 'text-orange-500' },
  fapello: { name: 'Fapello', icon: Image, color: 'text-red-500' },
  imagefap: { name: 'ImageFap', icon: Image, color: 'text-green-500' },
  rule34: { name: 'Rule34', icon: Image, color: 'text-green-600' },
  e621: { name: 'e621', icon: Image, color: 'text-blue-500' },
  nhentai: { name: 'nHentai', icon: Image, color: 'text-pink-500' },
  hitomi: { name: 'Hitomi', icon: Image, color: 'text-pink-500' },
  gelbooru: { name: 'Gelbooru', icon: Image, color: 'text-blue-500' },
  danbooru: { name: 'Danbooru', icon: Image, color: 'text-blue-500' },
  deviantart: { name: 'DeviantArt', icon: Image, color: 'text-green-500' },
  artstation: { name: 'ArtStation', icon: Image, color: 'text-blue-500' },
  pixiv: { name: 'Pixiv', icon: Image, color: 'text-blue-500' },
  furaffinity: { name: 'FurAffinity', icon: Image, color: 'text-orange-500' },
  catbox: { name: 'Catbox', icon: Folder, color: 'text-purple-500' },
}

interface VideoInfo {
  platform: string
  video_id: string
  url?: string
  title: string
  uploader: string
  upload_date: string | null
  duration: number
  description: string
  thumbnail: string
  view_count: number
  like_count: number
  already_downloaded: boolean
  is_playlist?: boolean
  playlist_count?: number
  playlist_videos?: VideoInfo[]
  // Gallery-specific fields
  is_gallery?: boolean
  file_count?: number
  image_count?: number
  video_count?: number
}

interface DownloadStatus {
  id: string
  platform: string
  video_id: string
  url: string
  status: 'pending' | 'downloading' | 'processing' | 'completed' | 'failed' | 'paused'
  progress: number
  message: string
  video_info: VideoInfo | null
  file_path: string | null
  error: string | null
  started_at: string
  speed?: string | null
  eta?: string | null
}

interface DownloadHistory {
  id: number
  platform: string
  video_id: string
  url: string
  title: string
  uploader: string
  upload_date: string | null
  duration: number
  file_path: string
  file_size: number
  download_date: string
  status: string
  thumbnail: string
  view_count: number
  like_count: number
  width: number | null
  height: number | null
}

// Queue item for download queue
interface QueueItem {
  id: string
  url: string
  platform: string
  video_id: string
  title: string
  thumbnail?: string
  status: 'queued' | 'downloading' | 'paused' | 'completed' | 'failed'
  progress: number
  speed?: string
  eta?: string
  error?: string
  addedAt: number
}

// Playlist video selection
interface PlaylistSelection {
  playlistUrl: string
  platform: string
  videos: VideoInfo[]
  selectedIds: Set<string>
}

type SortOption = 'date_desc' | 'date_asc' | 'size_desc' | 'size_asc' | 'duration_desc' | 'duration_asc' | 'title_asc' | 'title_desc'

const SORT_OPTIONS: { value: SortOption; label: string }[] = [
  { value: 'date_desc', label: 'Newest First' },
  { value: 'date_asc', label: 'Oldest First' },
  { value: 'size_desc', label: 'Largest First' },
  { value: 'size_asc', label: 'Smallest First' },
  { value: 'duration_desc', label: 'Longest First' },
  { value: 'duration_asc', label: 'Shortest First' },
  { value: 'title_asc', label: 'Title A-Z' },
  { value: 'title_desc', label: 'Title Z-A' },
]

// Helper to format duration
const formatDuration = (seconds: number): string => {
  if (!seconds) return ''
  const totalSeconds = Math.floor(seconds)
  const h = Math.floor(totalSeconds / 3600)
  const m = Math.floor((totalSeconds % 3600) / 60)
  const s = totalSeconds % 60
  if (h > 0) return `${h}:${m.toString().padStart(2, '0')}:${s.toString().padStart(2, '0')}`
  return `${m}:${s.toString().padStart(2, '0')}`
}

// Helper to detect Instagram post URLs
const isInstagramPostUrl = (url: string): boolean => {
  // Match instagram.com/p/XXX or imginn.com/p/XXX patterns
  const patterns = [
    /instagram\.com\/p\/([A-Za-z0-9_-]+)/,
    /instagram\.com\/reel\/([A-Za-z0-9_-]+)/,
    /imginn\.com\/p\/([A-Za-z0-9_-]+)/,
  ]
  return patterns.some(pattern => pattern.test(url))
}

// Extract post ID from Instagram URL
const extractInstagramPostId = (url: string): string | null => {
  const patterns = [
    /instagram\.com\/p\/([A-Za-z0-9_-]+)/,
    /instagram\.com\/reel\/([A-Za-z0-9_-]+)/,
    /imginn\.com\/p\/([A-Za-z0-9_-]+)/,
  ]
  for (const pattern of patterns) {
    const match = url.match(pattern)
    if (match) return match[1]
  }
  return null
}

export default function VideoDownloader() {
  useBreadcrumb(breadcrumbConfig['/videos'])
  const [urls, setUrls] = useState('')
  const [fetchingInfo, setFetchingInfo] = useState(false)
  const [activeDownloads, setActiveDownloads] = useState<Map<string, DownloadStatus>>(new Map())
  const [pollingKeys, setPollingKeys] = useState<Set<string>>(new Set())
  const [selectedMedia, setSelectedMedia] = useState<any>(null)

  // Download queue state
  const [downloadQueue, setDownloadQueue] = useState<QueueItem[]>([])
  const [isQueuePaused, setIsQueuePaused] = useState(false)
  const [maxConcurrent, setMaxConcurrent] = useState(2)
  const [showQueue, setShowQueue] = useState(false)

  // Playlist selection state
  const [playlistSelection, setPlaylistSelection] = useState<PlaylistSelection | null>(null)

  // Instagram post download state
  const [instagramDownloads, setInstagramDownloads] = useState<Map<string, { status: 'pending' | 'downloading' | 'completed' | 'failed'; message: string }>>(new Map())

  // Search, filter, and sort state
  const [searchQuery, setSearchQuery] = useState('')
  const [platformFilter, setPlatformFilter] = useState<string>('all')
  const [sortOption, setSortOption] = useState<SortOption>('date_desc')
  const [hoveredVideo, setHoveredVideo] = useState<string | null>(null)
  const fileInputRef = useRef<HTMLInputElement>(null)

  // Pagination state
  const [currentPage, setCurrentPage] = useState(1)
  const itemsPerPage = 24 // Load 24 items per page to limit thumbnail requests

  // Gallery lightbox state
  const [galleryFiles, setGalleryFiles] = useState<any[]>([])

  // Helper function to get thumbnail URL
  const getThumbnailUrl = (video: { video_id?: string; thumbnail?: string; platform?: string }, videoPlatform?: string, source: 'preview' | 'history' = 'preview') => {
    const videoId = video.video_id
    const thumbnail = video.thumbnail
    const plat = videoPlatform || video.platform || 'unknown'

    // Security: Auth via httpOnly cookie only - no token in URL
    if (videoId && plat !== 'unknown') {
      return `/api/video/thumbnail/${plat}/${videoId}?source=${source}`
    }

    if (!thumbnail) return ''

    // Proxy for Bilibili thumbnails - auth via cookie
    if (thumbnail.includes('hdslb.com') || plat === 'bilibili') {
      return `/api/video/thumbnail-proxy?url=${encodeURIComponent(thumbnail)}`
    }

    return thumbnail
  }

  // Get platform icon component
  const getPlatformIcon = (platform: string) => {
    return PLATFORMS[platform]?.icon || Video
  }

  const getPlatformColor = (platform: string) => {
    return PLATFORMS[platform]?.color || 'text-gray-500'
  }

  const getPlatformName = (platform: string) => {
    return PLATFORMS[platform]?.name || platform.charAt(0).toUpperCase() + platform.slice(1)
  }

  // Fetch preview list (all platforms in single call)
  const { data: previewListData, refetch: refetchPreviewList } = useQuery({
    queryKey: ['videoPreviewList', 'all'],
    queryFn: async () => {
      try {
        const response = await api.get('/video/preview-list') as any
        return response.preview_list || []
      } catch {
        return []
      }
    }
  })

  const videoInfoList = previewListData || []

  // Lightbox functions
  const openLightbox = async (item: any) => {
    setGalleryFiles([])

    try {
      // Fetch gallery files to see if this is a multi-file gallery
      const response = await api.getGalleryFiles(item.platform, item.video_id)

      if (response.files && response.files.length > 1) {
        // Multi-file gallery - create lightbox items for each file
        const galleryItems = response.files.map((file: any, index: number) => ({
          id: `${item.id}_${index}`,
          file_path: file.file_path,
          filename: file.filename,
          media_type: file.media_type,
          platform: item.platform,
          source: item.uploader,
          post_date: item.upload_date,
          download_date: item.download_date,
          file_size: file.file_size,
          width: file.width,
          height: file.height,
          video_id: item.video_id,
          title: item.title,
          metadata: {
            thumbnail: item.thumbnail,
            duration: item.duration,
            view_count: item.view_count,
            like_count: item.like_count,
            gallery_index: index + 1,
            gallery_total: response.files.length
          }
        }))
        setGalleryFiles(galleryItems)
        setSelectedMedia(galleryItems[0])
      } else {
        // Single file - use original behavior
        setGalleryFiles([])
        setSelectedMedia({
          id: item.id,
          file_path: item.file_path,
          filename: item.title,
          media_type: 'video',
          platform: item.platform,
          source: item.uploader,
          post_date: item.upload_date,
          download_date: item.download_date,
          file_size: item.file_size,
          width: item.width,
          height: item.height,
          video_id: item.video_id,
          title: item.title,
          metadata: {
            thumbnail: item.thumbnail,
            duration: item.duration,
            view_count: item.view_count,
            like_count: item.like_count
          }
        })
      }
    } catch (error) {
      console.error('Error fetching gallery files:', error)
      // Fallback to single item view
      setGalleryFiles([])
      setSelectedMedia({
        id: item.id,
        file_path: item.file_path,
        filename: item.title,
        media_type: 'video',
        platform: item.platform,
        source: item.uploader,
        post_date: item.upload_date,
        download_date: item.download_date,
        file_size: item.file_size,
        width: item.width,
        height: item.height,
        video_id: item.video_id,
        title: item.title,
        metadata: {
          thumbnail: item.thumbnail,
          duration: item.duration,
          view_count: item.view_count,
          like_count: item.like_count
        }
      })
    }
  }

  // Get items for lightbox - gallery files for multi-file, or all history items for filmstrip
  const getLightboxItems = () => {
    // If we have gallery files (multi-file gallery like Erome), show those
    if (galleryFiles.length > 0) {
      return galleryFiles
    }
    // Otherwise, show all videos from filteredHistory for filmstrip navigation
    return filteredHistory.map((item: DownloadHistory) => ({
      id: item.id,
      file_path: item.file_path,
      filename: item.title,
      media_type: 'video' as const,
      platform: item.platform,
      source: item.uploader,
      post_date: item.upload_date,
      download_date: item.download_date,
      file_size: item.file_size,
      width: item.width,
      height: item.height,
      video_id: item.video_id,
      title: item.title,
      metadata: {
        thumbnail: item.thumbnail,
        duration: item.duration,
        view_count: item.view_count,
        like_count: item.like_count
      }
    }))
  }

  const getCurrentLightboxIndex = () => {
    if (!selectedMedia) return -1
    // If viewing gallery files, find index in gallery
    if (galleryFiles.length > 0) {
      return galleryFiles.findIndex((item: any) => item.id === selectedMedia.id)
    }
    // Otherwise find index in filteredHistory
    return filteredHistory.findIndex((item: DownloadHistory) => item.id === selectedMedia.id)
  }

  // Mutation to remove from preview list
  const removeFromPreviewMutation = useMutation({
    mutationFn: async ({ plat, videoId }: { plat: string; videoId: string }) => {
      await api.delete(`/video/preview-list/${plat}/${videoId}`)
    },
    onSuccess: () => {
      refetchPreviewList()
    }
  })

  // Mutation to delete video (uses new endpoint that handles galleries)
  const deleteVideoMutation = useMutation({
    mutationFn: async (item: DownloadHistory) => {
      return await api.deleteVideoDownload(item.platform, item.video_id)
    },
    onSuccess: () => {
      refetchHistory()
      setSelectedMedia(null)
      setGalleryFiles([])
    }
  })

  const handleDeleteVideo = (item: DownloadHistory) => {
    if (confirm(`Delete "${item.title}"? This will move all files to the recycle bin.`)) {
      deleteVideoMutation.mutate(item)
    }
  }

  // Download Instagram post via ImgInn
  const downloadInstagramPost = async (url: string) => {
    const postId = extractInstagramPostId(url)
    if (!postId) return

    setInstagramDownloads(prev => {
      const next = new Map(prev)
      next.set(postId, { status: 'downloading', message: 'Starting download...' })
      return next
    })

    try {
      const response = await api.post('/instagram/download-post', { post_id: postId }) as any
      setInstagramDownloads(prev => {
        const next = new Map(prev)
        next.set(postId, { status: 'completed', message: response.message || 'Download started!' })
        return next
      })

      // Remove from display after 5 seconds
      setTimeout(() => {
        setInstagramDownloads(prev => {
          const next = new Map(prev)
          next.delete(postId)
          return next
        })
        refetchHistory()
      }, 5000)
    } catch (error: any) {
      setInstagramDownloads(prev => {
        const next = new Map(prev)
        next.set(postId, { status: 'failed', message: error.response?.data?.detail || error.message || 'Download failed' })
        return next
      })
    }
  }

  // Fetch video info for URLs (auto-detect platform)
  const fetchVideoInfo = async () => {
    const urlList = urls.trim().split('\n').filter(u => u.trim())
    if (urlList.length === 0) return

    setFetchingInfo(true)

    // Separate Instagram posts from other URLs
    const instagramPosts: string[] = []
    const otherUrls: string[] = []

    for (const url of urlList) {
      const trimmedUrl = url.trim()
      if (isInstagramPostUrl(trimmedUrl)) {
        instagramPosts.push(trimmedUrl)
      } else {
        otherUrls.push(trimmedUrl)
      }
    }

    // Download Instagram posts directly via ImgInn
    for (const url of instagramPosts) {
      await downloadInstagramPost(url)
    }

    // Process other URLs through normal video info flow
    for (const url of otherUrls) {
      try {
        // Backend auto-detects platform from URL
        const response = await api.post('/video/info', { url }) as any
        const videoInfo = response.info

        // Check if this is a playlist
        if (videoInfo.is_playlist && videoInfo.playlist_videos?.length > 0) {
          // Open playlist selection modal
          setPlaylistSelection({
            playlistUrl: url,
            platform: response.platform,
            videos: videoInfo.playlist_videos,
            selectedIds: new Set(videoInfo.playlist_videos.map((v: VideoInfo) => v.video_id))
          })
        } else {
          // Add single video to preview list
          await api.post('/video/preview-list/add', {
            platform: response.platform,
            video_info: videoInfo
          })
        }
      } catch (error: any) {
        console.error(`Failed to fetch info for ${url}:`, error)
      }
    }

    setUrls('')
    setFetchingInfo(false)
    refetchPreviewList()
  }

  // Remove video from preview
  const removeFromPreview = (video: VideoInfo) => {
    removeFromPreviewMutation.mutate({ plat: video.platform, videoId: video.video_id })
  }

  // Construct URL from video info
  const constructVideoUrl = (video: VideoInfo): string => {
    if (video.url) return video.url

    switch (video.platform) {
      case 'youtube':
        return `https://www.youtube.com/watch?v=${video.video_id}`
      case 'vimeo':
        return `https://vimeo.com/${video.video_id}`
      case 'dailymotion':
        return `https://www.dailymotion.com/video/${video.video_id}`
      case 'bilibili':
        const biliMatch = video.video_id.match(/^(BV[a-zA-Z0-9]+)_p(\d+)$/)
        if (biliMatch) {
          return `https://www.bilibili.com/video/${biliMatch[1]}?p=${biliMatch[2]}`
        }
        return `https://www.bilibili.com/video/${video.video_id}`
      default:
        return ''
    }
  }

  // Queue management functions
  const addToQueue = useCallback((items: { url: string; platform: string; video_id: string; title: string; thumbnail?: string }[]) => {
    const newItems: QueueItem[] = items.map(item => ({
      id: `${item.platform}:${item.video_id}`,
      url: item.url,
      platform: item.platform,
      video_id: item.video_id,
      title: item.title,
      thumbnail: item.thumbnail,
      status: 'queued' as const,
      progress: 0,
      addedAt: Date.now()
    }))

    setDownloadQueue(prev => {
      // Filter out duplicates
      const existingIds = new Set(prev.map(q => q.id))
      const uniqueNew = newItems.filter(item => !existingIds.has(item.id))
      return [...prev, ...uniqueNew]
    })

    if (!showQueue) setShowQueue(true)
  }, [showQueue])

  const removeFromQueue = useCallback((id: string) => {
    setDownloadQueue(prev => prev.filter(q => q.id !== id))
  }, [])

  const clearCompletedFromQueue = useCallback(() => {
    setDownloadQueue(prev => prev.filter(q => q.status !== 'completed' && q.status !== 'failed'))
  }, [])

  // Process queue - start downloads for queued items
  const processQueue = useCallback(async () => {
    if (isQueuePaused) return

    const activeCount = downloadQueue.filter(q => q.status === 'downloading').length
    const availableSlots = maxConcurrent - activeCount

    if (availableSlots <= 0) return

    const queuedItems = downloadQueue.filter(q => q.status === 'queued')
    const itemsToStart = queuedItems.slice(0, availableSlots)

    for (const item of itemsToStart) {
      try {
        // Update queue item status
        setDownloadQueue(prev => prev.map(q =>
          q.id === item.id ? { ...q, status: 'downloading' as const } : q
        ))

        // Start the download
        const response = await api.post('/video/download', {
          url: item.url,
          platform: item.platform,
          tracking_video_id: item.video_id
        }) as any

        const trackingKey = `${response.platform}:${response.video_id}`
        setPollingKeys(prev => new Set([...prev, trackingKey]))
      } catch (error: any) {
        console.error(`Failed to start download for ${item.video_id}:`, error)
        setDownloadQueue(prev => prev.map(q =>
          q.id === item.id ? { ...q, status: 'failed' as const, error: error.message } : q
        ))
      }
    }
  }, [downloadQueue, isQueuePaused, maxConcurrent])

  // Playlist selection functions
  const togglePlaylistVideo = useCallback((videoId: string) => {
    if (!playlistSelection) return

    setPlaylistSelection(prev => {
      if (!prev) return null
      const newSelected = new Set(prev.selectedIds)
      if (newSelected.has(videoId)) {
        newSelected.delete(videoId)
      } else {
        newSelected.add(videoId)
      }
      return { ...prev, selectedIds: newSelected }
    })
  }, [playlistSelection])

  const selectAllPlaylistVideos = useCallback(() => {
    if (!playlistSelection) return
    setPlaylistSelection(prev => {
      if (!prev) return null
      return { ...prev, selectedIds: new Set(prev.videos.map(v => v.video_id)) }
    })
  }, [playlistSelection])

  const deselectAllPlaylistVideos = useCallback(() => {
    if (!playlistSelection) return
    setPlaylistSelection(prev => {
      if (!prev) return null
      return { ...prev, selectedIds: new Set() }
    })
  }, [playlistSelection])

  const addSelectedPlaylistVideosToQueue = useCallback(() => {
    if (!playlistSelection || playlistSelection.selectedIds.size === 0) return

    const selectedVideos = playlistSelection.videos.filter(v =>
      playlistSelection.selectedIds.has(v.video_id) && !v.already_downloaded
    )

    const items = selectedVideos.map(video => ({
      url: constructVideoUrl(video),
      platform: video.platform,
      video_id: video.video_id,
      title: video.title,
      thumbnail: video.thumbnail
    }))

    addToQueue(items)
    setPlaylistSelection(null)
  }, [playlistSelection, addToQueue])

  // Download a single video
  const downloadSingleVideo = async (video: VideoInfo) => {
    if (video.already_downloaded) {
      alert('This video has already been downloaded.')
      return
    }

    try {
      const url = constructVideoUrl(video)
      const response = await api.post('/video/download', {
        url,
        platform: video.platform,
        tracking_video_id: video.video_id
      }) as any
      const trackingKey = `${response.platform}:${response.video_id}`
      setPollingKeys(prev => new Set([...prev, trackingKey]))
    } catch (error: any) {
      console.error(`Failed to start download for ${video.video_id}:`, error)
      alert(`Failed to start download: ${error.response?.data?.detail || error.message}`)
    }
  }

  // Start bulk downloads
  const startBulkDownloads = async () => {
    const videosToDownload = videoInfoList.filter((v: VideoInfo) => !v.already_downloaded)

    if (videosToDownload.length === 0) {
      alert('No videos to download.')
      return
    }

    for (const video of videosToDownload) {
      try {
        const url = constructVideoUrl(video)
        await api.post('/video/download', {
          url,
          platform: video.platform,
          tracking_video_id: video.video_id
        })
        const trackingKey = `${video.platform}:${video.video_id}`
        setPollingKeys(prev => new Set([...prev, trackingKey]))
      } catch (error: any) {
        console.error(`Failed to start download for ${video.video_id}:`, error)
      }
    }
  }

  const startDownloadMutation = useMutation({
    mutationFn: startBulkDownloads,
    onError: (error: any) => {
      alert(error.response?.data?.detail || 'Failed to start downloads')
    }
  })

  // Fetch history for all platforms with pagination
  const { data: historyData, refetch: refetchHistory, isLoading: isLoadingHistory } = useQuery({
    queryKey: ['videoHistory', 'all', currentPage, platformFilter, searchQuery, sortOption],
    queryFn: async () => {
      try {
        const offset = (currentPage - 1) * itemsPerPage
        // Build query params - backend handles filtering/sorting
        let url = `/video/history?limit=${itemsPerPage}&offset=${offset}`
        if (platformFilter !== 'all') {
          url += `&platform=${encodeURIComponent(platformFilter)}`
        }
        if (searchQuery) {
          url += `&search=${encodeURIComponent(searchQuery)}`
        }
        const response = await api.get(url) as any
        return {
          history: response.history || [],
          total: response.total || 0,
          platforms: response.platforms || [],
          platform_stats: response.platform_stats || {}
        }
      } catch {
        return { history: [], total: 0, platforms: [], platform_stats: {} }
      }
    }
  })

  const history: DownloadHistory[] = historyData?.history || []
  const totalItems: number = historyData?.total || 0
  const totalPages = Math.ceil(totalItems / itemsPerPage)

  // Reset to page 1 when filters change
  useEffect(() => {
    setCurrentPage(1)
  }, [platformFilter, searchQuery, sortOption])

  // Storage stats across all platforms (from API)
  const storageStats: Record<string, { count: number; size: number }> = historyData?.platform_stats || {}

  // Calculate total stats from platform stats
  const totalStats = Object.values(storageStats).reduce(
    (acc, stat) => ({ count: acc.count + stat.count, size: acc.size + stat.size }),
    { count: 0, size: 0 }
  )

  // Sort history (search is handled by backend)
  const filteredHistory = [...history].sort((a: DownloadHistory, b: DownloadHistory) => {
      switch (sortOption) {
        case 'date_desc': return new Date(b.download_date).getTime() - new Date(a.download_date).getTime()
        case 'date_asc': return new Date(a.download_date).getTime() - new Date(b.download_date).getTime()
        case 'size_desc': return (b.file_size || 0) - (a.file_size || 0)
        case 'size_asc': return (a.file_size || 0) - (b.file_size || 0)
        case 'duration_desc': return (b.duration || 0) - (a.duration || 0)
        case 'duration_asc': return (a.duration || 0) - (b.duration || 0)
        case 'title_asc': return (a.title || '').localeCompare(b.title || '')
        case 'title_desc': return (b.title || '').localeCompare(a.title || '')
        default: return 0
      }
    })

  // Handle file import
  const handleFileImport = (event: React.ChangeEvent<HTMLInputElement>) => {
    const file = event.target.files?.[0]
    if (!file) return

    const reader = new FileReader()
    reader.onload = (e) => {
      const content = e.target?.result as string
      if (content) {
        setUrls(prev => prev ? `${prev}\n${content.trim()}` : content.trim())
      }
    }
    reader.readAsText(file)
    event.target.value = ''
  }

  // Poll download statuses
  useEffect(() => {
    if (pollingKeys.size === 0) return

    const interval = setInterval(async () => {
      const completedKeys: string[] = []

      for (const trackingKey of pollingKeys) {
        try {
          const [plat, videoId] = trackingKey.split(':')
          const response = await api.get(`/video/status/${plat}/${videoId}`) as any

          setActiveDownloads(prev => {
            const next = new Map(prev)
            next.set(trackingKey, response.status)
            return next
          })

          // Update queue item progress and status
          setDownloadQueue(prev => prev.map(q => {
            if (q.id === trackingKey) {
              return {
                ...q,
                progress: response.status.progress || q.progress,
                speed: response.status.speed || q.speed,
                eta: response.status.eta || q.eta,
                status: response.status.status === 'completed' ? 'completed' :
                        response.status.status === 'failed' ? 'failed' :
                        q.status
              }
            }
            return q
          }))

          if (response.status.status === 'completed' || response.status.status === 'failed') {
            completedKeys.push(trackingKey)

            if (response.status.status === 'completed') {
              removeFromPreviewMutation.mutate({ plat, videoId })
            }

            setTimeout(() => {
              setActiveDownloads(prev => {
                const next = new Map(prev)
                next.delete(trackingKey)
                return next
              })
            }, 5000)
          }
        } catch (error) {
          console.error(`Error polling status for ${trackingKey}:`, error)
        }
      }

      if (completedKeys.length > 0) {
        setPollingKeys(prev => {
          const next = new Set(prev)
          completedKeys.forEach(key => next.delete(key))
          if (next.size === 0) {
            refetchHistory()
          }
          return next
        })
      }
    }, 1000)

    return () => clearInterval(interval)
  }, [pollingKeys.size])

  // Process queue when items are added or downloads complete
  useEffect(() => {
    const hasQueuedItems = downloadQueue.some(q => q.status === 'queued')
    const activeCount = downloadQueue.filter(q => q.status === 'downloading').length

    if (hasQueuedItems && activeCount < maxConcurrent && !isQueuePaused) {
      processQueue()
    }
  }, [downloadQueue, maxConcurrent, isQueuePaused, processQueue])

  // Get unique platforms from API response (all platforms with downloads)
  const uniquePlatforms: string[] = historyData?.platforms || []

  return (
    <div className="space-y-6">
      {/* Header with Storage Stats */}
      <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
        <div>
          <h1 className="text-2xl sm:text-3xl font-bold flex items-center gap-2 sm:gap-3">
            <Clapperboard className="w-8 h-8 text-rose-500" />
            Video Downloader
          </h1>
          <p className="text-slate-600 dark:text-slate-400 mt-1">
            Download videos from YouTube, Vimeo, Bilibili, Twitter, TikTok, and 1000+ more sites
          </p>
        </div>
        {totalStats.count > 0 && (
          <div className="flex items-center space-x-4 text-sm">
            <div className="flex items-center space-x-2 px-3 py-2 bg-secondary rounded-lg">
              <HardDrive className="w-4 h-4 text-muted-foreground" />
              <span className="text-foreground">
                {totalStats.count} videos • {formatBytes(totalStats.size)}
              </span>
            </div>
          </div>
        )}
      </div>

      {/* Download Form */}
      <div className="card-glass-hover rounded-xl p-6">
        <div className="space-y-4">
          <div>
            <label className="block text-sm font-medium text-foreground mb-2">
              Video URLs (one per line) - supports YouTube, Vimeo, Twitter, TikTok, Bilibili, and more
            </label>
            <textarea
              value={urls}
              onChange={(e) => setUrls(e.target.value)}
              placeholder="https://www.youtube.com/watch?v=...&#10;https://twitter.com/user/status/...&#10;https://www.tiktok.com/@user/video/...&#10;https://vimeo.com/..."
              rows={4}
              className="w-full px-4 py-2 border border-border rounded-lg bg-background text-foreground input-glow focus-ring font-mono text-sm"
              disabled={fetchingInfo || startDownloadMutation.isPending}
            />
          </div>

          <div className="flex flex-wrap gap-2">
            <input
              type="file"
              ref={fileInputRef}
              onChange={handleFileImport}
              accept=".txt,.csv"
              className="hidden"
            />
            <button
              onClick={() => fileInputRef.current?.click()}
              disabled={fetchingInfo || startDownloadMutation.isPending}
              className="px-4 py-2.5 bg-gray-600 text-white rounded-lg hover:bg-gray-700 disabled:opacity-50 flex items-center space-x-2 min-h-[44px]"
              title="Import URLs from text file"
            >
              <Upload className="w-5 h-5" />
              <span>Import</span>
            </button>
            <button
              onClick={fetchVideoInfo}
              disabled={!urls.trim() || fetchingInfo || startDownloadMutation.isPending}
              className="px-4 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 flex items-center space-x-2 btn-hover-lift min-h-[44px]"
            >
              {fetchingInfo ? (
                <><Loader2 className="w-5 h-5 animate-spin" /> <span>Loading...</span></>
              ) : (
                <><Info className="w-5 h-5" /> <span>Preview ({urls.trim().split('\n').filter(u => u.trim()).length})</span></>
              )}
            </button>
            <button
              onClick={() => {
                const videosToQueue = videoInfoList.filter((v: VideoInfo) => !v.already_downloaded)
                addToQueue(videosToQueue.map((video: VideoInfo) => ({
                  url: constructVideoUrl(video),
                  platform: video.platform,
                  video_id: video.video_id,
                  title: video.title,
                  thumbnail: video.thumbnail
                })))
              }}
              disabled={videoInfoList.filter((v: VideoInfo) => !v.already_downloaded).length === 0}
              className="px-4 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 flex items-center space-x-2 min-h-[44px]"
            >
              <List className="w-5 h-5" />
              <span>Queue All ({videoInfoList.filter((v: VideoInfo) => !v.already_downloaded).length})</span>
            </button>
            <button
              onClick={() => startDownloadMutation.mutate()}
              disabled={videoInfoList.filter((v: VideoInfo) => !v.already_downloaded).length === 0 || startDownloadMutation.isPending}
              className="flex-1 min-w-[150px] px-4 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 btn-hover-lift min-h-[44px]"
            >
              {startDownloadMutation.isPending ? (
                <><Loader2 className="w-5 h-5 animate-spin" /> <span>Starting...</span></>
              ) : (
                <><Download className="w-5 h-5" /> <span>Download All</span></>
              )}
            </button>
          </div>
        </div>

        {/* Video Previews */}
        {videoInfoList.length > 0 && (
          <div className="mt-6 border-t border-gray-200 dark:border-gray-700 pt-6">
            <h3 className="text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">
              Preview List ({videoInfoList.length} videos)
            </h3>
            <div className="space-y-3">
              {videoInfoList.map((video: VideoInfo) => {
                const PlatformIcon = getPlatformIcon(video.platform)
                return (
                  <div key={`${video.platform}:${video.video_id}`} className="flex items-start space-x-3 p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
                    {video.thumbnail && (
                      <img
                        src={getThumbnailUrl(video, video.platform, 'preview')}
                        alt={video.title}
                        className="w-24 h-14 object-cover rounded flex-shrink-0"
                        referrerPolicy="no-referrer"
                        onError={(e) => {
                          const target = e.target as HTMLImageElement
                          if (target.src !== video.thumbnail) {
                            target.src = video.thumbnail
                          } else {
                            target.style.display = 'none'
                          }
                        }}
                      />
                    )}
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center space-x-2">
                        <PlatformIcon className={`w-4 h-4 ${getPlatformColor(video.platform)}`} />
                        <span className="text-xs text-gray-500 dark:text-gray-400">{getPlatformName(video.platform)}</span>
                      </div>
                      <h4 className="font-medium text-gray-900 dark:text-white truncate">{video.title}</h4>
                      <div className="flex items-center space-x-3 text-xs text-gray-500 dark:text-gray-400 mt-1">
                        <span>{video.uploader}</span>
                        {video.duration > 0 && (
                          <span className="flex items-center space-x-1">
                            <Clock className="w-3 h-3" />
                            <span>{formatDuration(video.duration)}</span>
                          </span>
                        )}
                      </div>
                    </div>
                    <div className="flex items-center space-x-1">
                      {video.already_downloaded ? (
                        <span className="text-xs text-green-600 dark:text-green-400 flex items-center space-x-1">
                          <CheckCircle className="w-4 h-4" />
                          <span>Downloaded</span>
                        </span>
                      ) : (
                        <>
                          <button
                            onClick={() => addToQueue([{
                              url: constructVideoUrl(video),
                              platform: video.platform,
                              video_id: video.video_id,
                              title: video.title,
                              thumbnail: video.thumbnail
                            }])}
                            className="p-2 text-blue-600 hover:bg-blue-50 dark:hover:bg-blue-900/20 rounded"
                            title="Add to Queue"
                          >
                            <List className="w-4 h-4" />
                          </button>
                          <button
                            onClick={() => downloadSingleVideo(video)}
                            className="p-2 text-green-600 hover:bg-green-50 dark:hover:bg-green-900/20 rounded"
                            title="Download Now"
                          >
                            <Download className="w-4 h-4" />
                          </button>
                        </>
                      )}
                      <button
                        onClick={() => removeFromPreview(video)}
                        className="p-2 text-gray-400 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded"
                        title="Remove"
                      >
                        <X className="w-4 h-4" />
                      </button>
                    </div>
                  </div>
                )
              })}
            </div>
          </div>
        )}
      </div>

      {/* Active Downloads */}
      {activeDownloads.size > 0 && (
        <div className="card-glass-hover rounded-xl p-6">
          <h3 className="text-lg font-semibold text-foreground mb-4">
            Active Downloads ({activeDownloads.size})
          </h3>
          <div className="space-y-4">
            {Array.from(activeDownloads.values()).map((download) => {
              const DownloadIcon = getPlatformIcon(download.platform)
              return (
                <div key={`${download.platform}:${download.video_id}`} className="pb-4 border-b border-gray-200 dark:border-gray-700 last:border-0 last:pb-0">
                  <div className="flex items-start space-x-3">
                    {(download.video_info?.thumbnail || download.video_id) && (
                      <img
                        src={getThumbnailUrl({ video_id: download.video_id, thumbnail: download.video_info?.thumbnail, platform: download.platform }, download.platform, 'preview')}
                        alt={download.video_info?.title}
                        className="w-32 h-20 object-cover rounded flex-shrink-0"
                        referrerPolicy="no-referrer"
                        onError={(e) => {
                          const target = e.target as HTMLImageElement
                          const originalUrl = download.video_info?.thumbnail
                          if (originalUrl && target.src !== originalUrl) {
                            target.src = originalUrl
                          } else {
                            target.style.display = 'none'
                          }
                        }}
                      />
                    )}
                    <div className="flex-1 min-w-0 space-y-2">
                      <div className="flex items-center space-x-2">
                        <DownloadIcon className={`w-4 h-4 ${getPlatformColor(download.platform)}`} />
                        <span className="font-medium text-gray-900 dark:text-white truncate">{download.video_info?.title || download.video_id}</span>
                        <span className="text-sm font-bold text-blue-600 dark:text-blue-400 ml-auto flex-shrink-0">
                          {download.progress}%
                        </span>
                      </div>
                      <div className="w-full bg-gray-200 dark:bg-gray-700 rounded-full h-1.5 sm:h-2">
                        <div
                          className={`h-1.5 sm:h-2 rounded-full transition-all duration-300 ${
                            download.status === 'completed' ? 'bg-green-500' :
                            download.status === 'failed' ? 'bg-red-500' : 'bg-blue-500 progress-animated'
                          }`}
                          style={{ width: `${download.progress}%` }}
                        />
                      </div>
                      <div className="flex items-center space-x-3 text-xs">
                        {download.status === 'completed' && (
                          <span className="flex items-center space-x-1 text-green-600 dark:text-green-400">
                            <CheckCircle className="w-3 h-3" />
                            <span>Completed!</span>
                          </span>
                        )}
                        {download.status === 'failed' && (
                          <span className="flex items-center space-x-1 text-red-600 dark:text-red-400">
                            <XCircle className="w-3 h-3" />
                            <span>Error: {download.error}</span>
                          </span>
                        )}
                        {(download.status === 'downloading' || download.status === 'pending') && (
                          <>
                            <span className="flex items-center space-x-1 text-blue-600 dark:text-blue-400">
                              <span className="live-dot-blue"></span>
                              <span>Downloading...</span>
                            </span>
                            {download.speed && <span className="text-gray-500">{download.speed}</span>}
                            {download.eta && <span className="text-gray-500">ETA {download.eta}</span>}
                          </>
                        )}
                      </div>
                    </div>
                  </div>
                </div>
              )
            })}
          </div>
        </div>
      )}

      {/* Instagram Post Downloads */}
      {instagramDownloads.size > 0 && (
        <div className="card-glass-hover rounded-xl p-6">
          <h3 className="text-lg font-semibold text-foreground mb-4 flex items-center space-x-2">
            <Video className="w-5 h-5 text-pink-600" />
            <span>Instagram Post Downloads ({instagramDownloads.size})</span>
          </h3>
          <div className="space-y-3">
            {Array.from(instagramDownloads.entries()).map(([postId, download]) => (
              <div key={postId} className="flex items-center space-x-3 p-3 bg-gray-50 dark:bg-gray-700/50 rounded-lg">
                <div className="flex-shrink-0">
                  {download.status === 'downloading' && <Loader2 className="w-5 h-5 text-blue-500 animate-spin" />}
                  {download.status === 'completed' && <CheckCircle className="w-5 h-5 text-green-500" />}
                  {download.status === 'failed' && <XCircle className="w-5 h-5 text-red-500" />}
                </div>
                <div className="flex-1 min-w-0">
                  <div className="font-medium text-gray-900 dark:text-white">Post: {postId}</div>
                  <div className={`text-sm ${
                    download.status === 'completed' ? 'text-green-600 dark:text-green-400' :
                    download.status === 'failed' ? 'text-red-600 dark:text-red-400' :
                    'text-gray-600 dark:text-gray-400'
                  }`}>
                    {download.message}
                  </div>
                </div>
                {download.status === 'failed' && (
                  <button
                    onClick={() => setInstagramDownloads(prev => {
                      const next = new Map(prev)
                      next.delete(postId)
                      return next
                    })}
                    className="p-1 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200"
                  >
                    <X className="w-4 h-4" />
                  </button>
                )}
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Download History */}
      <div className="card-glass rounded-xl overflow-hidden">
        <div className="px-6 py-4 border-b border-border">
          <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-4">
            <div>
              <h3 className="text-lg font-semibold text-foreground">Download History</h3>
              <p className="text-sm text-muted-foreground">
                {isLoadingHistory ? 'Loading...' : (
                  searchQuery ? `${totalItems} matches` : `${totalItems} videos total`
                )}
              </p>
            </div>
            <div className="flex flex-wrap gap-2">
              {/* Platform Filter */}
              <select
                value={platformFilter}
                onChange={(e) => setPlatformFilter(e.target.value)}
                className="px-3 py-2 border border-border rounded-lg bg-background text-foreground text-sm"
              >
                <option value="all">All Platforms</option>
                {uniquePlatforms.map((plat: string) => (
                  <option key={plat} value={plat}>{getPlatformName(plat)} ({storageStats[plat]?.count || 0})</option>
                ))}
              </select>
              {/* Search */}
              <div className="relative">
                <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground" />
                <input
                  type="text"
                  placeholder="Search..."
                  value={searchQuery}
                  onChange={(e) => setSearchQuery(e.target.value)}
                  className="pl-9 pr-3 py-2 w-40 border border-border rounded-lg bg-background text-foreground text-sm input-glow focus-ring"
                />
              </div>
              {/* Sort */}
              <select
                value={sortOption}
                onChange={(e) => setSortOption(e.target.value as SortOption)}
                className="px-3 py-2 border border-border rounded-lg bg-background text-foreground text-sm"
              >
                {SORT_OPTIONS.map(opt => (
                  <option key={opt.value} value={opt.value}>{opt.label}</option>
                ))}
              </select>
            </div>
          </div>
        </div>

        <div className="divide-y divide-gray-200 dark:divide-gray-700 relative">
          {isLoadingHistory && (
            <div className="absolute inset-0 bg-white/50 dark:bg-gray-800/50 flex items-center justify-center z-10">
              <Loader2 className="w-8 h-8 text-blue-500 animate-spin" />
            </div>
          )}
          {filteredHistory.length > 0 ? (
            filteredHistory.map((item: DownloadHistory) => {
              const HistoryIcon = getPlatformIcon(item.platform)
              const isHovered = hoveredVideo === item.video_id
              return (
                <div key={item.id} className="p-4 hover:bg-gray-50 dark:hover:bg-gray-700/50 transition-colors">
                  <div className="flex space-x-3">
                    {(item.thumbnail || item.video_id) && (
                      <div
                        className="relative flex-shrink-0 group thumbnail-zoom overflow-hidden rounded"
                        onMouseEnter={() => setHoveredVideo(item.video_id)}
                        onMouseLeave={() => setHoveredVideo(null)}
                      >
                        <img
                          src={getThumbnailUrl(item, item.platform, 'history')}
                          alt={item.title}
                          onClick={() => openLightbox(item)}
                          className="w-32 h-20 object-cover cursor-pointer hover:opacity-80 transition-opacity"
                          referrerPolicy="no-referrer"
                          onError={(e) => {
                            const target = e.target as HTMLImageElement
                            if (item.thumbnail && target.src !== item.thumbnail) {
                              target.src = item.thumbnail
                            } else {
                              target.style.display = 'none'
                            }
                          }}
                        />
                        {isHovered && (
                          <div className="absolute left-0 top-full mt-2 z-50 hidden md:block">
                            <div className="bg-white dark:bg-gray-800 rounded-lg shadow-xl border border-gray-200 dark:border-gray-700 p-2 w-80">
                              <img
                                src={getThumbnailUrl(item, item.platform, 'history')}
                                alt={item.title}
                                className="w-full h-44 object-cover rounded"
                                referrerPolicy="no-referrer"
                                onError={(e) => {
                                  const target = e.target as HTMLImageElement
                                  if (item.thumbnail && target.src !== item.thumbnail) {
                                    target.src = item.thumbnail
                                  } else {
                                    target.style.display = 'none'
                                  }
                                }}
                              />
                              <p className="text-sm font-medium text-gray-900 dark:text-white mt-2 line-clamp-2">{item.title}</p>
                              <p className="text-xs text-gray-500 dark:text-gray-400">{item.uploader}</p>
                            </div>
                          </div>
                        )}
                      </div>
                    )}
                    <div className="flex-1 min-w-0">
                      <div className="flex items-center space-x-2 mb-1">
                        <HistoryIcon className={`w-4 h-4 ${getPlatformColor(item.platform)}`} />
                        <span className="text-xs text-gray-500 dark:text-gray-400">{getPlatformName(item.platform)}</span>
                      </div>
                      <h4 className="font-medium text-gray-900 dark:text-white truncate">{item.title}</h4>
                      <div className="flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-gray-600 dark:text-gray-400 mt-1">
                        <span>{item.uploader}</span>
                        {item.duration > 0 && (
                          <span className="flex items-center space-x-1">
                            <Clock className="w-3 h-3" />
                            <span>{formatDuration(item.duration)}</span>
                          </span>
                        )}
                        {item.file_size > 0 && <span>{formatBytes(item.file_size)}</span>}
                        <span>Downloaded: {formatDate(item.download_date)}</span>
                      </div>
                      <div className="text-xs text-gray-500 mt-1 truncate">{item.file_path}</div>
                    </div>
                    <div className="flex items-center space-x-2">
                      <CheckCircle className="w-5 h-5 text-green-500" />
                      <button
                        onClick={(e) => { e.stopPropagation(); handleDeleteVideo(item); }}
                        disabled={deleteVideoMutation.isPending}
                        className="p-1.5 text-gray-400 hover:text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded"
                        title="Delete"
                      >
                        <Trash2 className="w-4 h-4" />
                      </button>
                    </div>
                  </div>
                </div>
              )
            })
          ) : (
            <div className="p-8 text-center text-gray-500 dark:text-gray-400">
              <Video className="w-12 h-12 mx-auto mb-3 opacity-50" />
              {searchQuery || platformFilter !== 'all' ? (
                <>
                  <p>No matching videos</p>
                  <p className="text-sm">Try a different search or filter</p>
                </>
              ) : (
                <>
                  <p>No downloads yet</p>
                  <p className="text-sm">Enter a video URL above to get started</p>
                </>
              )}
            </div>
          )}
        </div>

        {/* Pagination Controls */}
        {totalPages > 1 && (
          <div className="px-6 py-4 border-t border-gray-200 dark:border-gray-700 flex items-center justify-between">
            <div className="text-sm text-gray-600 dark:text-gray-400">
              Showing {((currentPage - 1) * itemsPerPage) + 1} - {Math.min(currentPage * itemsPerPage, totalItems)} of {totalItems} videos
            </div>
            <div className="flex items-center space-x-2">
              <button
                onClick={() => setCurrentPage(1)}
                disabled={currentPage === 1 || isLoadingHistory}
                className="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed"
              >
                First
              </button>
              <button
                onClick={() => setCurrentPage(p => Math.max(1, p - 1))}
                disabled={currentPage === 1 || isLoadingHistory}
                className="p-1.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed"
              >
                <ChevronLeft className="w-4 h-4" />
              </button>
              <div className="flex items-center space-x-1">
                {/* Page numbers - show up to 5 pages around current */}
                {Array.from({ length: Math.min(5, totalPages) }, (_, i) => {
                  let pageNum: number
                  if (totalPages <= 5) {
                    pageNum = i + 1
                  } else if (currentPage <= 3) {
                    pageNum = i + 1
                  } else if (currentPage >= totalPages - 2) {
                    pageNum = totalPages - 4 + i
                  } else {
                    pageNum = currentPage - 2 + i
                  }
                  return (
                    <button
                      key={pageNum}
                      onClick={() => setCurrentPage(pageNum)}
                      disabled={isLoadingHistory}
                      className={`px-3 py-1.5 text-sm rounded-lg ${
                        currentPage === pageNum
                          ? 'bg-blue-600 text-white'
                          : 'border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600'
                      } disabled:opacity-50`}
                    >
                      {pageNum}
                    </button>
                  )
                })}
              </div>
              <button
                onClick={() => setCurrentPage(p => Math.min(totalPages, p + 1))}
                disabled={currentPage === totalPages || isLoadingHistory}
                className="p-1.5 border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed"
              >
                <ChevronRight className="w-4 h-4" />
              </button>
              <button
                onClick={() => setCurrentPage(totalPages)}
                disabled={currentPage === totalPages || isLoadingHistory}
                className="px-3 py-1.5 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-600 disabled:opacity-50 disabled:cursor-not-allowed"
              >
                Last
              </button>
            </div>
          </div>
        )}
      </div>

      {/* Download Queue Panel */}
      {downloadQueue.length > 0 && (
        <div className="card-glass rounded-xl overflow-hidden">
          <div
            className="px-6 py-4 flex items-center justify-between cursor-pointer hover:bg-secondary/50"
            onClick={() => setShowQueue(!showQueue)}
          >
            <div className="flex items-center space-x-3">
              <List className="w-5 h-5 text-blue-500" />
              <h3 className="text-lg font-semibold text-foreground">
                Download Queue ({downloadQueue.filter(q => q.status === 'queued' || q.status === 'downloading').length} pending)
              </h3>
            </div>
            <div className="flex items-center space-x-3">
              <button
                onClick={(e) => { e.stopPropagation(); setIsQueuePaused(!isQueuePaused); }}
                className={`px-3 py-1.5 rounded-lg flex items-center space-x-2 ${
                  isQueuePaused
                    ? 'bg-green-100 text-green-700 hover:bg-green-200 dark:bg-green-900/30 dark:text-green-400'
                    : 'bg-yellow-100 text-yellow-700 hover:bg-yellow-200 dark:bg-yellow-900/30 dark:text-yellow-400'
                }`}
              >
                {isQueuePaused ? <Play className="w-4 h-4" /> : <Pause className="w-4 h-4" />}
                <span>{isQueuePaused ? 'Resume' : 'Pause'}</span>
              </button>
              <select
                value={maxConcurrent}
                onChange={(e) => { e.stopPropagation(); setMaxConcurrent(Number(e.target.value)); }}
                onClick={(e) => e.stopPropagation()}
                className="px-2 py-1 text-sm border border-border rounded bg-background text-foreground"
              >
                <option value={1}>1 concurrent</option>
                <option value={2}>2 concurrent</option>
                <option value={3}>3 concurrent</option>
                <option value={4}>4 concurrent</option>
              </select>
              {showQueue ? <ChevronUp className="w-5 h-5 text-gray-400" /> : <ChevronDown className="w-5 h-5 text-gray-400" />}
            </div>
          </div>

          {showQueue && (
            <div className="border-t border-gray-200 dark:border-gray-700">
              <div className="px-6 py-2 bg-gray-50 dark:bg-gray-700/50 flex justify-between items-center">
                <span className="text-sm text-gray-600 dark:text-gray-400">
                  {downloadQueue.filter(q => q.status === 'completed').length} completed,
                  {' '}{downloadQueue.filter(q => q.status === 'failed').length} failed
                </span>
                <button
                  onClick={clearCompletedFromQueue}
                  className="text-sm text-blue-600 hover:text-blue-700 dark:text-blue-400"
                >
                  Clear completed
                </button>
              </div>
              <div className="divide-y divide-gray-200 dark:divide-gray-700 max-h-80 overflow-y-auto custom-scrollbar">
                {downloadQueue.map((item) => {
                  const QueueIcon = getPlatformIcon(item.platform)
                  return (
                    <div key={item.id} className="px-6 py-3 flex items-center space-x-3">
                      {item.thumbnail && (
                        <img
                          src={getThumbnailUrl({ video_id: item.video_id, thumbnail: item.thumbnail, platform: item.platform }, item.platform, 'preview')}
                          alt={item.title}
                          className="w-16 h-10 object-cover rounded flex-shrink-0"
                          referrerPolicy="no-referrer"
                          onError={(e) => {
                            const target = e.target as HTMLImageElement
                            if (item.thumbnail && target.src !== item.thumbnail) {
                              target.src = item.thumbnail
                            } else {
                              target.style.display = 'none'
                            }
                          }}
                        />
                      )}
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center space-x-2">
                          <QueueIcon className={`w-3 h-3 ${getPlatformColor(item.platform)}`} />
                          <span className="font-medium text-gray-900 dark:text-white text-sm truncate">{item.title}</span>
                        </div>
                        {item.status === 'downloading' && (
                          <div className="mt-1 flex items-center space-x-2">
                            <div className="flex-1 bg-gray-200 dark:bg-gray-700 rounded-full h-1.5">
                              <div
                                className="bg-blue-500 h-1.5 rounded-full transition-all"
                                style={{ width: `${item.progress}%` }}
                              />
                            </div>
                            <span className="text-xs text-gray-500">{item.progress}%</span>
                            {item.speed && <span className="text-xs text-gray-500">{item.speed}</span>}
                          </div>
                        )}
                        {item.status === 'queued' && (
                          <span className="text-xs text-gray-500 dark:text-gray-400">Queued</span>
                        )}
                        {item.status === 'completed' && (
                          <span className="text-xs text-green-600 dark:text-green-400 flex items-center space-x-1">
                            <CheckCircle className="w-3 h-3" /> <span>Completed</span>
                          </span>
                        )}
                        {item.status === 'failed' && (
                          <span className="text-xs text-red-600 dark:text-red-400 flex items-center space-x-1">
                            <XCircle className="w-3 h-3" /> <span>{item.error || 'Failed'}</span>
                          </span>
                        )}
                      </div>
                      <button
                        onClick={() => removeFromQueue(item.id)}
                        className="p-1 text-gray-400 hover:text-red-500 rounded"
                        title="Remove from queue"
                      >
                        <X className="w-4 h-4" />
                      </button>
                    </div>
                  )
                })}
              </div>
            </div>
          )}
        </div>
      )}

      {/* Lightbox */}
      {selectedMedia && getCurrentLightboxIndex() >= 0 && (
        <EnhancedLightbox
          items={getLightboxItems()}
          currentIndex={getCurrentLightboxIndex()}
          onClose={() => {
            setSelectedMedia(null)
            setGalleryFiles([])
          }}
          onNavigate={(newIndex) => {
            const items = getLightboxItems()
            if (items[newIndex]) {
              setSelectedMedia(items[newIndex])
            }
          }}
          onDelete={(item) => {
            // Find the original history item to delete (deletes whole gallery)
            const historyItem = filteredHistory.find((h: any) => h.video_id === item.video_id)
            if (historyItem) {
              handleDeleteVideo(historyItem)
            }
          }}
          getPreviewUrl={(item) => api.getMediaPreviewUrl(item.file_path, item.file_token)}
          getThumbnailUrl={(item) => api.getMediaThumbnailUrl(item.file_path, item.media_type === 'video' ? 'video' : 'image', item.file_token)}
          isVideo={(item) => item.media_type === 'video'}
          renderActions={(item) => (
            <button
              onClick={() => {
                const historyItem = filteredHistory.find((h: any) => h.video_id === item.video_id)
                if (historyItem) {
                  handleDeleteVideo(historyItem)
                }
              }}
              disabled={deleteVideoMutation.isPending}
              className="px-4 py-2.5 bg-red-600 text-white rounded-lg hover:bg-red-700 disabled:opacity-50 flex items-center space-x-2 min-h-[44px] transition-colors"
            >
              <Trash2 className="w-4 h-4" />
              <span>{deleteVideoMutation.isPending ? 'Deleting...' : 'Delete All'}</span>
            </button>
          )}
        />
      )}

      {/* Playlist Selection Modal */}
      {playlistSelection && (
        <div className="fixed inset-0 bg-black/50 backdrop-blur-sm flex items-center justify-center z-50 p-4">
          <div className="bg-card border border-border rounded-xl shadow-2xl max-w-4xl w-full max-h-[90vh] flex flex-col">
            <div className="px-6 py-4 border-b border-border flex items-center justify-between">
              <div>
                <h3 className="text-lg font-semibold text-foreground">
                  Select Videos from Playlist
                </h3>
                <p className="text-sm text-muted-foreground">
                  {playlistSelection.selectedIds.size} of {playlistSelection.videos.length} selected
                </p>
              </div>
              <button
                onClick={() => setPlaylistSelection(null)}
                className="p-2 text-gray-400 hover:text-gray-600 dark:hover:text-gray-200 rounded"
              >
                <X className="w-5 h-5" />
              </button>
            </div>

            <div className="px-6 py-3 bg-secondary/50 flex items-center justify-between">
              <div className="flex items-center space-x-3">
                <button
                  onClick={selectAllPlaylistVideos}
                  className="text-sm text-primary hover:text-primary/80"
                >
                  Select All
                </button>
                <button
                  onClick={deselectAllPlaylistVideos}
                  className="text-sm text-muted-foreground hover:text-foreground"
                >
                  Deselect All
                </button>
              </div>
              <span className="text-sm text-muted-foreground">
                {getPlatformName(playlistSelection.platform)}
              </span>
            </div>

            <div className="flex-1 overflow-y-auto p-6">
              <div className="space-y-2">
                {playlistSelection.videos.map((video, index) => {
                  const isSelected = playlistSelection.selectedIds.has(video.video_id)
                  const PlatIcon = getPlatformIcon(video.platform)
                  return (
                    <div
                      key={video.video_id}
                      onClick={() => !video.already_downloaded && togglePlaylistVideo(video.video_id)}
                      className={`flex items-center space-x-3 p-3 rounded-lg cursor-pointer transition-colors ${
                        video.already_downloaded
                          ? 'bg-gray-100 dark:bg-gray-700/30 opacity-60 cursor-not-allowed'
                          : isSelected
                            ? 'bg-blue-50 dark:bg-blue-900/20 border border-blue-200 dark:border-blue-800'
                            : 'bg-gray-50 dark:bg-gray-700/50 hover:bg-gray-100 dark:hover:bg-gray-700'
                      }`}
                    >
                      <div className="flex-shrink-0">
                        {video.already_downloaded ? (
                          <CheckCircle className="w-5 h-5 text-green-500" />
                        ) : isSelected ? (
                          <CheckSquare className="w-5 h-5 text-blue-500" />
                        ) : (
                          <Square className="w-5 h-5 text-gray-400" />
                        )}
                      </div>
                      <span className="text-sm text-gray-500 dark:text-gray-400 w-8">{index + 1}</span>
                      {video.thumbnail && (
                        <img
                          src={getThumbnailUrl(video, video.platform, 'preview')}
                          alt={video.title}
                          className="w-20 h-12 object-cover rounded flex-shrink-0"
                          referrerPolicy="no-referrer"
                          onError={(e) => {
                            const target = e.target as HTMLImageElement
                            if (target.src !== video.thumbnail) {
                              target.src = video.thumbnail
                            } else {
                              target.style.display = 'none'
                            }
                          }}
                        />
                      )}
                      <div className="flex-1 min-w-0">
                        <div className="flex items-center space-x-2">
                          <PlatIcon className={`w-3 h-3 ${getPlatformColor(video.platform)}`} />
                          <h4 className="font-medium text-gray-900 dark:text-white text-sm truncate">{video.title}</h4>
                        </div>
                        <div className="flex items-center space-x-3 text-xs text-gray-500 dark:text-gray-400 mt-1">
                          <span>{video.uploader}</span>
                          {video.duration > 0 && <span>{formatDuration(video.duration)}</span>}
                          {video.already_downloaded && <span className="text-green-600 dark:text-green-400">Already downloaded</span>}
                        </div>
                      </div>
                    </div>
                  )
                })}
              </div>
            </div>

            <div className="px-6 py-4 border-t border-border flex justify-end space-x-3">
              <button
                onClick={() => setPlaylistSelection(null)}
                className="px-4 py-2 text-muted-foreground hover:bg-secondary rounded-lg transition-colors"
              >
                Cancel
              </button>
              <button
                onClick={addSelectedPlaylistVideosToQueue}
                disabled={playlistSelection.selectedIds.size === 0}
                className="px-4 py-2.5 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 flex items-center space-x-2 min-h-[44px]"
              >
                <List className="w-4 h-4" />
                <span>Add {playlistSelection.selectedIds.size} to Queue</span>
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}
