import { useEffect, useState, useMemo, useRef } from 'react'
import { photosApi, PhotoSearchResult } from '../api/photos'
import tagsApi, { TagResponse, PhotoTagItem } from '../api/tags'
import { apiClient } from '../api/client'
import PhotoViewer from '../components/PhotoViewer'
import { useAuth } from '../context/AuthContext'
import peopleApi, { Person } from '../api/people'

type SearchType = 'name' | 'date' | 'tags' | 'no_faces' | 'no_tags' | 'processed' | 'unprocessed' | 'favorites'

const SEARCH_TYPES: { value: SearchType; label: string }[] = [
  { value: 'name', label: 'By person name' },
  { value: 'date', label: 'By date range' },
  { value: 'tags', label: 'By tags' },
  { value: 'no_faces', label: 'Photos without faces' },
  { value: 'no_tags', label: 'Photos without tags' },
  { value: 'processed', label: 'Processed photos' },
  { value: 'unprocessed', label: 'Unprocessed photos' },
  { value: 'favorites', label: '⭐ Favorite photos' },
]

type SortColumn = 'person' | 'tags' | 'processed' | 'path' | 'date_taken'
type SortDir = 'asc' | 'desc'

// Format person name for display
const formatPersonName = (person: Person): string => {
  const parts: string[] = []
  if (person.first_name) parts.push(person.first_name)
  if (person.middle_name) parts.push(person.middle_name)
  if (person.last_name) parts.push(person.last_name)
  if (person.maiden_name) parts.push(`(${person.maiden_name})`)
  return parts.join(' ') || 'Unknown'
}

export default function Search() {
  const { hasPermission } = useAuth()
  const canTagPhotos = hasPermission('tag_photos')
  const canDeletePhotos = hasPermission('faces_maintenance')
  const [searchType, setSearchType] = useState<SearchType>('name')
  const [tagsExpanded, setTagsExpanded] = useState(true) // Default to expanded
  const [filtersExpanded, setFiltersExpanded] = useState(false) // Default to collapsed
  const [configExpanded, setConfigExpanded] = useState(true) // Default to expanded
  
  // Search inputs
  const [selectedTags, setSelectedTags] = useState<string[]>([])
  const [matchAll, setMatchAll] = useState(false)
  const [dateFrom, setDateFrom] = useState('')
  const [dateTo, setDateTo] = useState('')
  const [dateTakenFrom, setDateTakenFrom] = useState('')
  const [dateTakenTo, setDateTakenTo] = useState('')
  const [mediaType, setMediaType] = useState<string>('all') // Default to 'all'
  
  // Person autocomplete
  const [allPeople, setAllPeople] = useState<Person[]>([])
  const [selectedPeople, setSelectedPeople] = useState<Person[]>([])
  const [showPeopleDropdown, setShowPeopleDropdown] = useState(false)
  const [inputValue, setInputValue] = useState('') // Current text being typed
  const personInputRef = useRef<HTMLInputElement>(null)
  const personDropdownRef = useRef<HTMLDivElement>(null)
  
  // Results
  const [results, setResults] = useState<PhotoSearchResult[]>([])
  const [total, setTotal] = useState(0)
  const [page, setPage] = useState(1)
  const [pageSize] = useState(50)
  const [loading, setLoading] = useState(false)
  
  // Selection
  const [selectedPhotos, setSelectedPhotos] = useState<Set<number>>(new Set())
  
  // Sorting
  const [sortColumn, setSortColumn] = useState<SortColumn | null>(null)
  const [sortDir, setSortDir] = useState<SortDir>('asc')
  
  // Tags
  const [availableTags, setAvailableTags] = useState<TagResponse[]>([])
  const [tagSearchInput, setTagSearchInput] = useState('')
  const [showTagDropdown, setShowTagDropdown] = useState(false)
  const tagInputRef = useRef<HTMLInputElement>(null)
  const tagDropdownRef = useRef<HTMLDivElement>(null)
  
  // SessionStorage key for persisting search state (clears when tab/window closes)
  const SEARCH_STATE_KEY = 'search_page_state'
  
  // Track if we're restoring state to prevent clearing during restoration
  const isRestoringState = useRef(false)
  
  // Tag modal
  const [showTagModal, setShowTagModal] = useState(false)
  const [selectedTagName, setSelectedTagName] = useState('')
  const [newTagName, setNewTagName] = useState('')
  const [photoTags, setPhotoTags] = useState<Record<number, PhotoTagItem[]>>({})
  const [selectedTagIds, setSelectedTagIds] = useState<Set<number>>(new Set())
  const [loadingTags, setLoadingTags] = useState(false)
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
  const [loadingFavorites, setLoadingFavorites] = useState(false)
  const [deletingPhotos, setDeletingPhotos] = useState(false)

  // Photo viewer
  const [showPhotoViewer, setShowPhotoViewer] = useState(false)
  const [allPhotos, setAllPhotos] = useState<PhotoSearchResult[]>([])
  const [loadingAllPhotos, setLoadingAllPhotos] = useState(false)
  const [photoViewerIndex, setPhotoViewerIndex] = useState(0)

  const loadTags = async () => {
    try {
      const res = await tagsApi.list()
      setAvailableTags(res.items)
    } catch (error) {
      console.error('Error loading tags:', error)
    }
  }

  const loadAllPeople = async () => {
    try {
      const res = await peopleApi.list()
      setAllPeople(res.items)
    } catch (error) {
      console.error('Error loading people:', error)
    }
  }

  // Load state from sessionStorage on mount
  useEffect(() => {
    let restoredSearchType: SearchType | null = null
    
    try {
      isRestoringState.current = true
      const savedState = sessionStorage.getItem(SEARCH_STATE_KEY)
      if (savedState) {
        const state = JSON.parse(savedState)
        // Restore all state values
        if (state.searchType) {
          restoredSearchType = state.searchType
          setSearchType(state.searchType)
        }
        if (state.selectedTags) setSelectedTags(state.selectedTags)
        if (state.matchAll !== undefined) setMatchAll(state.matchAll)
        if (state.dateFrom) setDateFrom(state.dateFrom)
        if (state.dateTo) setDateTo(state.dateTo)
        if (state.dateTakenFrom) setDateTakenFrom(state.dateTakenFrom)
        if (state.dateTakenTo) setDateTakenTo(state.dateTakenTo)
        if (state.mediaType) setMediaType(state.mediaType)
        if (state.selectedPeople) setSelectedPeople(state.selectedPeople)
        if (state.inputValue) setInputValue(state.inputValue)
        if (state.tagsExpanded !== undefined) setTagsExpanded(state.tagsExpanded)
        if (state.filtersExpanded !== undefined) setFiltersExpanded(state.filtersExpanded)
        if (state.configExpanded !== undefined) setConfigExpanded(state.configExpanded)
        if (state.sortColumn) setSortColumn(state.sortColumn)
        if (state.sortDir) setSortDir(state.sortDir)
        if (state.page) setPage(state.page)
        // Restore results if they exist
        if (state.results && Array.isArray(state.results)) {
          setResults(state.results)
        }
        if (state.total !== undefined) {
          setTotal(state.total)
        }
      }
    } catch (error) {
      console.error('Error loading saved search state:', error)
    } finally {
      // Mark restoration as complete after a short delay to allow all state updates to process
      setTimeout(() => {
        isRestoringState.current = false
        // Re-run auto-searches after restoration completes
        if (restoredSearchType && 
            (restoredSearchType === 'no_faces' || 
             restoredSearchType === 'no_tags' || 
             restoredSearchType === 'processed' || 
             restoredSearchType === 'unprocessed' || 
             restoredSearchType === 'favorites')) {
          // Use a small delay to ensure state is fully restored
          // Don't show validation errors for auto-searches
          // Pass the restored search type directly to avoid stale state issues
          setTimeout(() => {
            performSearch(undefined, false, restoredSearchType ?? undefined)
          }, 150)
        }
      }, 100)
    }
    
    loadTags()
    loadAllPeople()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [])

  // Save state to sessionStorage whenever relevant values change
  useEffect(() => {
    // Don't save during state restoration
    if (isRestoringState.current) {
      return
    }
    
    try {
      const stateToSave = {
        searchType,
        selectedTags,
        matchAll,
        dateFrom,
        dateTo,
        dateTakenFrom,
        dateTakenTo,
        mediaType,
        selectedPeople,
        inputValue,
        tagsExpanded,
        filtersExpanded,
        configExpanded,
        sortColumn,
        sortDir,
        page,
        results,
        total,
      }
      sessionStorage.setItem(SEARCH_STATE_KEY, JSON.stringify(stateToSave))
    } catch (error) {
      console.error('Error saving search state:', error)
    }
  }, [searchType, selectedTags, matchAll, dateFrom, dateTo, dateTakenFrom, dateTakenTo, mediaType, selectedPeople, inputValue, tagsExpanded, filtersExpanded, configExpanded, sortColumn, sortDir, page, results, total])

  const performSearch = async (pageNum: number = page, showValidationErrors: boolean = true, searchTypeOverride?: SearchType) => {
    setLoading(true)
    try {
      // Use override if provided (for state restoration), otherwise use current state
      const currentSearchType = searchTypeOverride ?? searchType
      const params: any = {
        search_type: currentSearchType,
        page: pageNum,
        page_size: pageSize,
      }

      // For "Photos without faces" search, always exclude videos
      if (currentSearchType === 'no_faces') {
        params.media_type = 'image'
      } else if (mediaType && mediaType !== 'all') {
        // Add media type filter if not 'all' for other search types
        params.media_type = mediaType
      }

      if (currentSearchType === 'name') {
        // Combine selected people names and free text input
        // For selected people, use last name (most unique) or first+last if last name is empty
        const selectedNames = selectedPeople.map(p => {
          if (p.last_name) {
            return p.last_name.trim()
          } else if (p.first_name) {
            return p.first_name.trim()
          }
          return formatPersonName(p).trim()
        })
        const freeText = inputValue.trim()
        const allNames = [...selectedNames, freeText].filter(Boolean)
        
        if (allNames.length === 0) {
          if (showValidationErrors) {
            alert('Please enter at least one name or select a person to search.')
          }
          setLoading(false)
          return
        }
        params.person_name = allNames.join(', ')
        // Add tags filter if provided
        if (selectedTags.length > 0) {
          params.tag_names = selectedTags.join(', ')
          params.match_all = matchAll
        }
      } else if (currentSearchType === 'date') {
        if (!dateFrom && !dateTo) {
          if (showValidationErrors) {
            alert('Please enter at least one date (from date or to date).')
          }
          setLoading(false)
          return
        }
        params.date_from = dateFrom || undefined
        params.date_to = dateTo || undefined
        // Add tags filter if provided
        if (selectedTags.length > 0) {
          params.tag_names = selectedTags.join(', ')
          params.match_all = matchAll
        }
      } else {
        // For non-date search types, apply date taken filter if provided
        if (dateTakenFrom || dateTakenTo) {
          params.date_from = dateTakenFrom || undefined
          params.date_to = dateTakenTo || undefined
        }
      }
      
      if (currentSearchType === 'tags') {
        if (selectedTags.length === 0) {
          if (showValidationErrors) {
            alert('Please select at least one tag to search for.')
          }
          setLoading(false)
          return
        }
        params.tag_names = selectedTags.join(', ')
        params.match_all = matchAll
      }

      const res = await photosApi.searchPhotos(params)
      setResults(res.items)
      setTotal(res.total)
      
      // Auto-run search for no_faces and no_tags
      // No alert shown when no photos found
    } catch (error: any) {
      console.error('Error searching photos:', error)
      const errorMessage = error.response?.data?.detail || error.message || 'Unknown error'
      alert(`Error searching photos: ${errorMessage}\n\nPlease check:\n1. Backend API is running (http://127.0.0.1:8000)\n2. You are logged in\n3. Database connection is working`)
    } finally {
      setLoading(false)
    }
  }

  const handleSearch = () => {
    setPage(1)
    setSelectedPhotos(new Set())
    performSearch(1, true) // Show validation errors when user explicitly clicks search
  }

  // Filter people for dropdown based on input
  const filteredPeopleForDropdown = useMemo(() => {
    if (!inputValue.trim()) {
      return allPeople.filter(p => !selectedPeople.some(sp => sp.id === p.id))
    }
    const query = inputValue.trim().toLowerCase()
    return allPeople.filter(person => {
      // Don't show already selected people
      if (selectedPeople.some(sp => sp.id === person.id)) return false
      
      const lastName = (person.last_name || '').toLowerCase()
      const firstName = (person.first_name || '').toLowerCase()
      const middleName = (person.middle_name || '').toLowerCase()
      const maidenName = (person.maiden_name || '').toLowerCase()
      const fullName = formatPersonName(person).toLowerCase()
      
      return fullName.includes(query) || 
             lastName.includes(query) || 
             firstName.includes(query) ||
             middleName.includes(query) ||
             maidenName.includes(query)
    })
  }, [inputValue, allPeople, selectedPeople])

  // Handle selecting a person from dropdown
  const handleSelectPerson = (person: Person) => {
    if (!selectedPeople.some(sp => sp.id === person.id)) {
      setSelectedPeople([...selectedPeople, person])
    }
    setInputValue('')
    setShowPeopleDropdown(false)
    personInputRef.current?.focus()
  }

  // Handle removing a selected person
  const handleRemovePerson = (personId: number) => {
    setSelectedPeople(selectedPeople.filter(p => p.id !== personId))
  }

  // Close dropdown when clicking outside
  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        personDropdownRef.current &&
        !personDropdownRef.current.contains(event.target as Node) &&
        personInputRef.current &&
        !personInputRef.current.contains(event.target as Node)
      ) {
        setShowPeopleDropdown(false)
      }
    }

    document.addEventListener('mousedown', handleClickOutside)
    return () => {
      document.removeEventListener('mousedown', handleClickOutside)
    }
  }, [])

  useEffect(() => {
    // Don't clear state during restoration
    if (isRestoringState.current) {
      return
    }
    
    // Clear results from previous search when search type changes
    setResults([])
    setTotal(0)
    setPage(1)
    setSelectedPhotos(new Set())
    
    if (searchType === 'no_faces' || searchType === 'no_tags' || searchType === 'processed' || searchType === 'unprocessed' || searchType === 'favorites') {
      handleSearch()
    }
    // Clear selected tags when switching away from tag/name/date search types
    if (searchType !== 'tags' && searchType !== 'name' && searchType !== 'date') {
      setSelectedTags([])
    }
    // Clear person autocomplete when switching away from name search
    if (searchType !== 'name') {
      setSelectedPeople([])
      setInputValue('')
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [searchType])

  const handleSort = (column: SortColumn) => {
    if (sortColumn === column) {
      setSortDir(sortDir === 'asc' ? 'desc' : 'asc')
    } else {
      setSortColumn(column)
      setSortDir('asc')
    }
  }

  const sortedResults = [...results].sort((a, b) => {
    if (!sortColumn) return 0
    
    let aVal: any
    let bVal: any
    
    switch (sortColumn) {
      case 'person':
        aVal = a.person_name || ''
        bVal = b.person_name || ''
        break
      case 'tags':
        aVal = a.tags.join(', ')
        bVal = b.tags.join(', ')
        break
      case 'processed':
        aVal = a.processed ? 'Yes' : 'No'
        bVal = b.processed ? 'Yes' : 'No'
        break
      case 'path':
        aVal = a.path
        bVal = b.path
        break
      case 'date_taken':
        aVal = a.date_taken || '9999-12-31'
        bVal = b.date_taken || '9999-12-31'
        break
    }
    
    if (typeof aVal === 'string') {
      aVal = aVal.toLowerCase()
      bVal = bVal.toLowerCase()
    }
    
    if (aVal < bVal) return sortDir === 'asc' ? -1 : 1
    if (aVal > bVal) return sortDir === 'asc' ? 1 : -1
    return 0
  })

  const toggleSelection = (photoId: number) => {
    setSelectedPhotos(prev => {
      const newSet = new Set(prev)
      if (newSet.has(photoId)) {
        newSet.delete(photoId)
      } else {
        newSet.add(photoId)
      }
      return newSet
    })
  }

  const clearAllSelected = () => {
    setSelectedPhotos(new Set())
  }

  const selectAll = () => {
    const allPhotoIds = new Set(results.map(photo => photo.id))
    setSelectedPhotos(allPhotoIds)
  }

  const loadPhotoTags = async () => {
    if (selectedPhotos.size === 0) return
    
    setLoadingTags(true)
    try {
      const tagsMap: Record<number, PhotoTagItem[]> = {}
      const photoIds = Array.from(selectedPhotos)
      
      // Load tags for each selected photo
      for (const photoId of photoIds) {
        try {
          const response = await tagsApi.getPhotoTags(photoId)
          tagsMap[photoId] = response.tags || []
        } catch (error) {
          console.error(`Error loading tags for photo ${photoId}:`, error)
          tagsMap[photoId] = []
        }
      }
      
      setPhotoTags(tagsMap)
    } catch (error) {
      console.error('Error loading photo tags:', error)
    } finally {
      setLoadingTags(false)
    }
  }

  // Load tags for selected photos when dialog opens
  useEffect(() => {
    if (showTagModal && selectedPhotos.size > 0) {
      loadPhotoTags()
    } else {
      setPhotoTags({})
      setSelectedTagIds(new Set())
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [showTagModal, selectedPhotos.size])

  // Get all unique tags from selected photos
  // Include all tags (both single and bulk) that are present in all selected photos
  const allPhotoTags = useMemo(() => {
    if (selectedPhotos.size === 0) return []
    
    const photoIds = Array.from(selectedPhotos)
    const tagMap = new Map<number, PhotoTagItem>()
    
    // First, collect all tags from all photos
    Object.values(photoTags).forEach(tags => {
      tags.forEach(tag => {
        if (!tagMap.has(tag.tag_id)) {
          tagMap.set(tag.tag_id, tag)
        }
      })
    })
    
    // Filter to only include tags that exist in ALL selected photos (both single and bulk)
    const commonTags = Array.from(tagMap.values()).filter(tag => {
      // Check if this tag exists in all selected photos
      return photoIds.every(photoId => {
        const photoTagList = photoTags[photoId] || []
        const photoTag = photoTagList.find(t => t.tag_id === tag.tag_id)
        // Tag must exist in photo
        return photoTag !== undefined
      })
    })
    
    return commonTags
  }, [photoTags, selectedPhotos])

  const handleSelectExistingTag = async (tagName: string) => {
    if (selectedPhotos.size === 0 || !tagName.trim()) {
      return
    }
    
    try {
      // Add the selected tag to photos
      await tagsApi.addToPhotos({
        photo_ids: Array.from(selectedPhotos),
        tag_names: [tagName.trim()],
      })
      
      // Clear the dropdown selection
      setSelectedTagName('')
      // Reload tags for selected photos so the new tag appears in the Tags area
      await loadPhotoTags()
    } catch (error) {
      console.error('Error tagging photos:', error)
      alert('Error tagging photos. Please try again.')
    }
  }

  const handleAddTag = async () => {
    if (selectedPhotos.size === 0) {
      alert('Please select photos to tag.')
      return
    }
    
    // Collect both tags: selected existing tag and new tag name
    const tagsToAdd: string[] = []
    
    if (selectedTagName.trim()) {
      tagsToAdd.push(selectedTagName.trim())
    }
    
    if (newTagName.trim()) {
      tagsToAdd.push(newTagName.trim())
    }
    
    if (tagsToAdd.length === 0) {
      alert('Please select a tag or enter a new tag name.')
      return
    }
    
    try {
      // Create any new tags first
      const newTags = tagsToAdd.filter(tag => 
        !availableTags.some(availableTag => 
          availableTag.tag_name.toLowerCase() === tag.toLowerCase()
        )
      )
      
      for (const newTag of newTags) {
        await tagsApi.create(newTag)
      }
      
      // Refresh available tags list if we created any
      if (newTags.length > 0) {
        await loadTags()
      }
      
      // Add all tags to photos in a single API call
      await tagsApi.addToPhotos({
        photo_ids: Array.from(selectedPhotos),
        tag_names: tagsToAdd,
      })
      
      // Clear inputs after successful tagging
      setSelectedTagName('')
      setNewTagName('')
      // Reload tags for selected photos
      await loadPhotoTags()
    } catch (error) {
      console.error('Error tagging photos:', error)
      alert('Error tagging photos. Please try again.')
    }
  }

  const handleDeleteTags = () => {
    if (selectedTagIds.size === 0) {
      alert('Please select tags to delete.')
      return
    }
    
    if (selectedPhotos.size === 0) {
      alert('No photos selected.')
      return
    }
    
    // Show confirmation dialog
    setShowDeleteConfirm(true)
  }

  const confirmDeleteTags = async () => {
    setShowDeleteConfirm(false)
    
    // Get tag names from selected tag IDs
    // Allow removing both single and bulk tags
    const tagNamesToDelete = Array.from(selectedTagIds)
      .map(tagId => {
        const tag = allPhotoTags.find(t => t.tag_id === tagId)
        return tag ? tag.tag_name : null
      })
      .filter(Boolean) as string[]
    
    if (tagNamesToDelete.length === 0) {
      alert('No tags selected to remove.')
      return
    }
    
    try {
      await tagsApi.removeFromPhotos({
        photo_ids: Array.from(selectedPhotos),
        tag_names: tagNamesToDelete,
      })
      
      setSelectedTagIds(new Set())
      // Reload tags for selected photos
      await loadPhotoTags()
    } catch (error) {
      console.error('Error removing tags:', error)
      alert('Error removing tags. Please try again.')
    }
  }

  // Get selected tag names for confirmation message
  const selectedTagNames = useMemo(() => {
    return Array.from(selectedTagIds)
      .map(tagId => {
        const tag = allPhotoTags.find(t => t.tag_id === tagId)
        return tag ? tag.tag_name : ''
      })
      .filter(Boolean)
      .join(', ')
  }, [selectedTagIds, allPhotoTags])

  const openPhoto = (photoId: number) => {
    const photoUrl = `${apiClient.defaults.baseURL}/api/v1/photos/${photoId}/image`
    window.open(photoUrl, '_blank')
  }

  const openFolder = async (photoId: number) => {
    try {
      const result = await photosApi.openFolder(photoId)
      // Success - folder opened in file manager
      // Optionally show a brief message
      console.log('Folder opened:', result.folder)
    } catch (error: any) {
      console.error('Error opening folder:', error)
      const errorMessage = error?.response?.data?.detail || error?.message || 'Failed to open folder'
      alert(`Error opening folder: ${errorMessage}`)
    }
  }

  const handleAddToFavorites = async () => {
    if (selectedPhotos.size === 0) {
      alert('Please select photos to add to favorites.')
      return
    }

    setLoadingFavorites(true)
    try {
      const photoIds = Array.from(selectedPhotos)

      // Use bulk endpoint for better performance
      await photosApi.bulkAddFavorites(photoIds)

      // Refresh search results to update favorite status
      await performSearch(page)

      // Clear selection after successful operation
      setSelectedPhotos(new Set())
    } catch (error) {
      console.error('Error adding photos to favorites:', error)
    } finally {
      setLoadingFavorites(false)
    }
  }

  const handleRemoveFromFavorites = async () => {
    if (selectedPhotos.size === 0) {
      alert('Please select photos to remove from favorites.')
      return
    }

    setLoadingFavorites(true)
    try {
      const photoIds = Array.from(selectedPhotos)

      // Use bulk endpoint for better performance
      await photosApi.bulkRemoveFavorites(photoIds)

      // Refresh search results to update favorite status
      await performSearch(page)

      // Clear selection after successful operation
      setSelectedPhotos(new Set())
    } catch (error) {
      console.error('Error removing photos from favorites:', error)
    } finally {
      setLoadingFavorites(false)
    }
  }

  const handleDeleteSelectedPhotos = async () => {
    if (selectedPhotos.size === 0) {
      alert('Please select photos to delete.')
      return
    }

    const warningLines = [
      `⚠️ WARNING: Permanently delete ${selectedPhotos.size} photo(s)?`,
      '',
    ]

    warningLines.push('This action CANNOT be undone. Continue?')

    if (!confirm(warningLines.join('\n'))) {
      return
    }

    setDeletingPhotos(true)
    try {
      const response = await photosApi.bulkDeletePhotos(Array.from(selectedPhotos))
      const missingNote = response.missing_photo_ids.length > 0
        ? `\nMissing photo IDs: ${response.missing_photo_ids.join(', ')}`
        : ''
      alert(`${response.message}${missingNote}`)
      await performSearch(page)
      setSelectedPhotos(new Set())
    } catch (error: any) {
      console.error('Error deleting photos:', error)
      const errorMessage = error?.response?.data?.detail || error?.message || 'Failed to delete photos.'
      alert(`Error deleting photos: ${errorMessage}`)
    } finally {
      setDeletingPhotos(false)
    }
  }

  const handleToggleFavorite = async (photoId: number) => {
    try {
      await photosApi.toggleFavorite(photoId)
      // Refresh search results to update favorite status
      await performSearch(page)
    } catch (error) {
      console.error(`Error toggling favorite for photo ${photoId}:`, error)
    }
  }

  // Load all photos for photo viewer (all pages)
  const loadAllPhotos = async () => {
    if (total === 0) {
      alert('No photos to display.')
      return
    }

    setLoadingAllPhotos(true)
    try {
      const allPhotosList: PhotoSearchResult[] = []
      const maxPageSize = 200 // Maximum allowed by API
      const totalPages = Math.ceil(total / maxPageSize)

      // Build search params (same as current search)
      const baseParams: any = {
        search_type: searchType,
        page_size: maxPageSize,
      }

      // Add media type filter if not 'all'
      if (mediaType && mediaType !== 'all') {
        baseParams.media_type = mediaType
      }

      if (searchType === 'name') {
        // Combine selected people names and free text input
        // For selected people, use last name (most unique) or first+last if last name is empty
        const selectedNames = selectedPeople.map(p => {
          if (p.last_name) {
            return p.last_name.trim()
          } else if (p.first_name) {
            return p.first_name.trim()
          }
          return formatPersonName(p).trim()
        })
        const freeText = inputValue.trim()
        const allNames = [...selectedNames, freeText].filter(Boolean)
        if (allNames.length > 0) {
          baseParams.person_name = allNames.join(', ')
        }
        // Add tags filter if provided
        if (selectedTags.length > 0) {
          baseParams.tag_names = selectedTags.join(', ')
          baseParams.match_all = matchAll
        }
      } else if (searchType === 'date') {
        baseParams.date_from = dateFrom || undefined
        baseParams.date_to = dateTo || undefined
        // Add tags filter if provided
        if (selectedTags.length > 0) {
          baseParams.tag_names = selectedTags.join(', ')
          baseParams.match_all = matchAll
        }
      } else {
        // For non-date search types, apply date taken filter if provided
        if (dateTakenFrom || dateTakenTo) {
          baseParams.date_from = dateTakenFrom || undefined
          baseParams.date_to = dateTakenTo || undefined
        }
      }
      
      if (searchType === 'tags') {
        baseParams.tag_names = selectedTags.join(', ')
        baseParams.match_all = matchAll
      }

      // Fetch all pages sequentially
      for (let pageNum = 1; pageNum <= totalPages; pageNum++) {
        const res = await photosApi.searchPhotos({
          ...baseParams,
          page: pageNum,
        })
        allPhotosList.push(...res.items)
      }

      setAllPhotos(allPhotosList)

      // Determine starting index
      let startIndex = 0
      if (selectedPhotos.size > 0) {
        // Start with first selected photo
        const selectedArray = Array.from(selectedPhotos)
        const firstSelectedId = selectedArray[0]
        const foundIndex = allPhotosList.findIndex(p => p.id === firstSelectedId)
        if (foundIndex !== -1) {
          startIndex = foundIndex
        }
      } else if (results.length > 0) {
        // Start with first photo in current results
        const firstResultId = results[0].id
        const foundIndex = allPhotosList.findIndex(p => p.id === firstResultId)
        if (foundIndex !== -1) {
          startIndex = foundIndex
        }
      }

      setPhotoViewerIndex(startIndex)
      setShowPhotoViewer(true)
    } catch (error) {
      console.error('Error loading all photos:', error)
      alert('Error loading photos. Please try again.')
    } finally {
      setLoadingAllPhotos(false)
    }
  }

  return (
    <div>
      {/* Collapsible Configuration Area */}
      <div className="bg-white rounded-lg shadow mb-2">
        <button
          onClick={() => setConfigExpanded(!configExpanded)}
          className="w-full flex items-center gap-2 p-2 hover:bg-gray-50 rounded-t-lg"
        >
          <span className="text-lg font-bold text-indigo-600">{configExpanded ? '−' : '+'}</span>
          <span className="text-sm font-medium text-gray-700">Search options</span>
        </button>
        
        {configExpanded && (
          <div className="p-2 space-y-2">
            {/* Search Type Selector */}
            <div className="bg-gray-50 rounded-lg shadow py-2 px-4">
              <div className="flex items-center gap-2">
                <label htmlFor="search-type-select" className="text-sm font-medium text-gray-700 whitespace-nowrap">
                  Search by
                </label>
                <select
                  id="search-type-select"
                  value={searchType}
                  onChange={(e) => setSearchType(e.target.value as SearchType)}
                  className="border rounded px-3 py-2"
                >
                  {SEARCH_TYPES.map(type => (
                    <option key={type.value} value={type.value}>{type.label}</option>
                  ))}
                </select>
              </div>
            </div>

                  {/* Search Inputs */}
            {(searchType !== 'no_faces' && searchType !== 'no_tags' && searchType !== 'processed' && searchType !== 'unprocessed') && (
              <div className="bg-gray-50 rounded-lg shadow py-2 px-4">
          {searchType === 'name' && (
          <div className="space-y-2">
            <label htmlFor="person-name-input" className="text-sm font-medium text-gray-700">
              Person names
            </label>
            
            {/* Selected people chips */}
            {selectedPeople.length > 0 && (
              <div className="mb-2">
                <div className="flex flex-wrap gap-2 mb-2">
                  {selectedPeople.map((person) => (
                    <span
                      key={person.id}
                      className="inline-flex items-center gap-1 px-2 py-1 bg-blue-100 text-blue-800 rounded text-sm"
                    >
                      {formatPersonName(person)}
                      <button
                        type="button"
                        onClick={() => handleRemovePerson(person.id)}
                        className="hover:text-blue-600 font-bold"
                        title="Remove person"
                        aria-label={`Remove ${formatPersonName(person)}`}
                      >
                        ×
                      </button>
                    </span>
                  ))}
                </div>
                <button
                  type="button"
                  onClick={() => {
                    setSelectedPeople([])
                    setResults([])
                    setTotal(0)
                    setPage(1)
                  }}
                  className="text-xs text-gray-600 hover:text-gray-800 underline"
                  title="Clear all selected people and search results"
                >
                  Clear all
                </button>
              </div>
            )}
            
            {/* Input with dropdown */}
            <div className="relative">
              <input
                id="person-name-input"
                ref={personInputRef}
                type="text"
                value={inputValue}
                onChange={(e) => {
                  setInputValue(e.target.value)
                  setShowPeopleDropdown(true)
                }}
                onFocus={() => setShowPeopleDropdown(true)}
                onKeyDown={(e) => {
                  if (e.key === 'Enter') {
                    e.preventDefault()
                    handleSearch()
                  } else if (e.key === 'Escape') {
                    setShowPeopleDropdown(false)
                  }
                }}
                className="w-96 border rounded px-3 py-2"
                placeholder="Type a name or select from list..."
              />
              
              {/* Dropdown */}
              {showPeopleDropdown && (
                <div
                  ref={personDropdownRef}
                  className="absolute z-50 w-1/2 mt-1 bg-white border border-gray-300 rounded-md shadow-lg max-h-60 overflow-auto"
                  style={{ top: '100%' }}
                >
                  {filteredPeopleForDropdown.length > 0 ? (
                    filteredPeopleForDropdown.map((person) => (
                      <div
                        key={person.id}
                        onClick={() => handleSelectPerson(person)}
                        className="px-3 py-2 hover:bg-blue-50 cursor-pointer"
                      >
                        <div className="flex items-center gap-2">
                          <span className="font-medium">{formatPersonName(person)}</span>
                          {person.date_of_birth && (
                            <span className="text-xs text-gray-500">Born: {person.date_of_birth}</span>
                          )}
                        </div>
                      </div>
                    ))
                  ) : (
                    <div className="px-3 py-2 text-sm text-gray-500">
                      {inputValue.trim() ? 'No matching people found' : 'Start typing to search for people'}
                    </div>
                  )}
                </div>
              )}
            </div>
            
            <p className="text-xs text-gray-500">
              Select people from the dropdown or type names manually. Separate multiple names with commas.
            </p>
            
            {/* Tags filter for name search */}
            <div className="mt-4">
              <div className="flex items-center gap-2">
                <h2 className="text-sm font-medium text-gray-700">Filter by tags (optional)</h2>
                <button
                  onClick={() => setTagsExpanded(!tagsExpanded)}
                  className="text-lg text-gray-600 hover:text-gray-800"
                  title={tagsExpanded ? 'Collapse tags section' : 'Expand tags section'}
                  aria-label={tagsExpanded ? 'Collapse tags section' : 'Expand tags section'}
                >
                  {tagsExpanded ? '▼' : '▶'}
                </button>
              </div>
              {tagsExpanded && (
                <div className="mt-3 space-y-2">
                  <div>
                    <label htmlFor="tag-search-input-name" className="block text-sm font-medium text-gray-700 mb-1">
                      Add tags
                    </label>
                    {/* Selected tags display */}
                    {selectedTags.length > 0 && (
                      <div className="mb-2">
                        <div className="flex flex-wrap gap-2 mb-2">
                          {selectedTags.map(tag => (
                            <span
                              key={tag}
                              className="inline-flex items-center gap-1 px-2 py-1 bg-blue-100 text-blue-800 rounded text-sm"
                            >
                              {tag}
                              <button
                                onClick={() => {
                                  setSelectedTags(selectedTags.filter(t => t !== tag))
                                }}
                                className="hover:text-blue-600"
                                type="button"
                              >
                                ×
                              </button>
                            </span>
                          ))}
                        </div>
                        <button
                          type="button"
                          onClick={() => {
                            setSelectedTags([])
                          }}
                          className="text-xs text-gray-600 hover:text-gray-800 underline"
                          title="Clear all selected tags"
                        >
                          Clear all
                        </button>
                      </div>
                    )}
                    {/* Tag input and dropdown */}
                    <div className="relative">
                      <input
                        id="tag-search-input-name"
                        ref={tagInputRef}
                        type="text"
                        value={tagSearchInput}
                        onChange={(e) => {
                          setTagSearchInput(e.target.value)
                          setShowTagDropdown(true)
                        }}
                        onFocus={() => setShowTagDropdown(true)}
                        onBlur={(e) => {
                          setTimeout(() => {
                            if (!tagDropdownRef.current?.contains(e.relatedTarget as Node)) {
                              setShowTagDropdown(false)
                            }
                          }, 200)
                        }}
                        placeholder="Type to search and select tags..."
                        className="w-full border rounded px-3 py-2 text-sm"
                      />
                      {showTagDropdown && (
                        <div
                          ref={tagDropdownRef}
                          className="absolute z-10 w-full mt-1 bg-white border rounded shadow-lg max-h-60 overflow-auto"
                          onMouseDown={(e) => e.preventDefault()}
                        >
                          {(() => {
                            const filtered = availableTags.filter(tag =>
                              tag.tag_name.toLowerCase().includes(tagSearchInput.toLowerCase()) &&
                              !selectedTags.includes(tag.tag_name)
                            )
                            return filtered.length > 0 ? (
                              filtered.map(tag => (
                                <div
                                  key={tag.id}
                                  onClick={() => {
                                    if (!selectedTags.includes(tag.tag_name)) {
                                      setSelectedTags([...selectedTags, tag.tag_name])
                                    }
                                    setTagSearchInput('')
                                    setTimeout(() => {
                                      setShowTagDropdown(true)
                                      tagInputRef.current?.focus()
                                    }, 0)
                                  }}
                                  className="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm"
                                >
                                  {tag.tag_name}
                                </div>
                              ))
                            ) : (
                              <div className="px-3 py-2 text-gray-500 text-sm">
                                {tagSearchInput.trim() ? 'No matching tags found' : 'Start typing to search for tags'}
                              </div>
                            )
                          })()}
                        </div>
                      )}
                    </div>
                  </div>
                  <div>
                    <label htmlFor="match-mode-select-name" className="block text-sm font-medium text-gray-700 mb-1">
                      Match mode
                    </label>
                    <select
                      id="match-mode-select-name"
                      value={matchAll ? 'ALL' : 'ANY'}
                      onChange={(e) => setMatchAll(e.target.value === 'ALL')}
                      className="border rounded px-3 py-2"
                    >
                      <option value="ANY">Match any tag (photos with at least one selected tag)</option>
                      <option value="ALL">Match all tags (photos with all selected tags)</option>
                    </select>
                  </div>
                </div>
              )}
            </div>
          </div>
        )}
        
        {searchType === 'date' && (
          <div className="space-y-4">
            <div className="flex items-end gap-4">
              <div>
                <label htmlFor="date-from-input" className="block text-sm font-medium text-gray-700 mb-1">
                  Start date
                </label>
                <input
                  id="date-from-input"
                  type="date"
                  value={dateFrom}
                  onChange={(e) => setDateFrom(e.target.value)}
                  className="w-48 border rounded px-3 py-2"
                />
              </div>
              <div>
                <label htmlFor="date-to-input" className="block text-sm font-medium text-gray-700 mb-1">
                  End date <span className="text-gray-500 font-normal">(optional)</span>
                </label>
                <input
                  id="date-to-input"
                  type="date"
                  value={dateTo}
                  onChange={(e) => setDateTo(e.target.value)}
                  className="w-48 border rounded px-3 py-2"
                />
              </div>
            </div>
            {/* Tags filter for date search */}
            <div className="w-1/2">
              <div className="flex items-center gap-2">
                <h2 className="text-sm font-medium text-gray-700">Filter by tags (optional)</h2>
                <button
                  onClick={() => setTagsExpanded(!tagsExpanded)}
                  className="text-lg text-gray-600 hover:text-gray-800"
                  title={tagsExpanded ? 'Collapse tags section' : 'Expand tags section'}
                  aria-label={tagsExpanded ? 'Collapse tags section' : 'Expand tags section'}
                >
                  {tagsExpanded ? '▼' : '▶'}
                </button>
              </div>
              {tagsExpanded && (
                <div className="mt-3 space-y-2">
                  <div>
                    <label htmlFor="tag-search-input-date" className="block text-sm font-medium text-gray-700 mb-1">
                      Add tags
                    </label>
                    {/* Selected tags display */}
                    {selectedTags.length > 0 && (
                      <div className="mb-2">
                        <div className="flex flex-wrap gap-2 mb-2">
                          {selectedTags.map(tag => (
                            <span
                              key={tag}
                              className="inline-flex items-center gap-1 px-2 py-1 bg-blue-100 text-blue-800 rounded text-sm"
                            >
                              {tag}
                              <button
                                onClick={() => {
                                  setSelectedTags(selectedTags.filter(t => t !== tag))
                                }}
                                className="hover:text-blue-600"
                                type="button"
                              >
                                ×
                              </button>
                            </span>
                          ))}
                        </div>
                        <button
                          type="button"
                          onClick={() => {
                            setSelectedTags([])
                          }}
                          className="text-xs text-gray-600 hover:text-gray-800 underline"
                          title="Clear all selected tags"
                        >
                          Clear all
                        </button>
                      </div>
                    )}
                    {/* Tag input and dropdown */}
                    <div className="relative">
                      <input
                        id="tag-search-input-date"
                        ref={tagInputRef}
                        type="text"
                        value={tagSearchInput}
                        onChange={(e) => {
                          setTagSearchInput(e.target.value)
                          setShowTagDropdown(true)
                        }}
                        onFocus={() => setShowTagDropdown(true)}
                        onBlur={(e) => {
                          setTimeout(() => {
                            if (!tagDropdownRef.current?.contains(e.relatedTarget as Node)) {
                              setShowTagDropdown(false)
                            }
                          }, 200)
                        }}
                        placeholder="Type to search and select tags..."
                        className="w-full border rounded px-3 py-2 text-sm"
                      />
                      {showTagDropdown && (
                        <div
                          ref={tagDropdownRef}
                          className="absolute z-10 w-full mt-1 bg-white border rounded shadow-lg max-h-60 overflow-auto"
                          onMouseDown={(e) => e.preventDefault()}
                        >
                          {(() => {
                            const filtered = availableTags.filter(tag =>
                              tag.tag_name.toLowerCase().includes(tagSearchInput.toLowerCase()) &&
                              !selectedTags.includes(tag.tag_name)
                            )
                            return filtered.length > 0 ? (
                              filtered.map(tag => (
                                <div
                                  key={tag.id}
                                  onClick={() => {
                                    if (!selectedTags.includes(tag.tag_name)) {
                                      setSelectedTags([...selectedTags, tag.tag_name])
                                    }
                                    setTagSearchInput('')
                                    setTimeout(() => {
                                      setShowTagDropdown(true)
                                      tagInputRef.current?.focus()
                                    }, 0)
                                  }}
                                  className="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm"
                                >
                                  {tag.tag_name}
                                </div>
                              ))
                            ) : (
                              <div className="px-3 py-2 text-gray-500 text-sm">
                                {tagSearchInput.trim() ? 'No matching tags found' : 'Start typing to search for tags'}
                              </div>
                            )
                          })()}
                        </div>
                      )}
                    </div>
                  </div>
                  <div>
                    <label htmlFor="match-mode-select-date" className="block text-sm font-medium text-gray-700 mb-1">
                      Match mode
                    </label>
                    <select
                      id="match-mode-select-date"
                      value={matchAll ? 'ALL' : 'ANY'}
                      onChange={(e) => setMatchAll(e.target.value === 'ALL')}
                      className="border rounded px-3 py-2"
                    >
                      <option value="ANY">Match any tag (photos with at least one selected tag)</option>
                      <option value="ALL">Match all tags (photos with all selected tags)</option>
                    </select>
                  </div>
                </div>
              )}
            </div>
          </div>
        )}
        
        {searchType === 'tags' && (
          <div className="w-1/2">
            <div className="flex items-center gap-2">
              <h2 className="text-sm font-medium text-gray-700">Select tags</h2>
              <button
                onClick={() => setTagsExpanded(!tagsExpanded)}
                className="text-lg text-gray-600 hover:text-gray-800"
                title={tagsExpanded ? 'Collapse tags section' : 'Expand tags section'}
                aria-label={tagsExpanded ? 'Collapse tags section' : 'Expand tags section'}
              >
                {tagsExpanded ? '▼' : '▶'}
              </button>
            </div>
            {tagsExpanded && (
              <div className="mt-3 space-y-2">
                <div>
                  <label htmlFor="tag-search-input" className="block text-sm font-medium text-gray-700 mb-1">
                    Add tags
                  </label>
                  {/* Selected tags display */}
                  {selectedTags.length > 0 && (
                    <div className="mb-2">
                      <div className="flex flex-wrap gap-2 mb-2">
                        {selectedTags.map(tag => (
                          <span
                            key={tag}
                            className="inline-flex items-center gap-1 px-2 py-1 bg-blue-100 text-blue-800 rounded text-sm"
                          >
                            {tag}
                            <button
                              onClick={() => {
                                setSelectedTags(selectedTags.filter(t => t !== tag))
                              }}
                              className="hover:text-blue-600"
                              type="button"
                            >
                              ×
                            </button>
                          </span>
                        ))}
                      </div>
                      <button
                        type="button"
                        onClick={() => {
                          setSelectedTags([])
                        }}
                        className="text-xs text-gray-600 hover:text-gray-800 underline"
                        title="Clear all selected tags"
                      >
                        Clear all
                      </button>
                    </div>
                  )}
                  {/* Tag input and dropdown */}
                  <div className="relative">
                    <input
                      id="tag-search-input"
                      ref={tagInputRef}
                      type="text"
                      value={tagSearchInput}
                      onChange={(e) => {
                        setTagSearchInput(e.target.value)
                        setShowTagDropdown(true)
                      }}
                      onFocus={() => setShowTagDropdown(true)}
                      onBlur={(e) => {
                        // Delay to allow click on dropdown items
                        setTimeout(() => {
                          if (!tagDropdownRef.current?.contains(e.relatedTarget as Node)) {
                            setShowTagDropdown(false)
                          }
                        }, 200)
                      }}
                      placeholder="Type to search and select tags..."
                      className="w-full border rounded px-3 py-2 text-sm"
                    />
                    {showTagDropdown && (
                      <div
                        ref={tagDropdownRef}
                        className="absolute z-10 w-full mt-1 bg-white border rounded shadow-lg max-h-60 overflow-auto"
                        onMouseDown={(e) => e.preventDefault()} // Prevent blur on click
                      >
                        {(() => {
                          const filtered = availableTags.filter(tag =>
                            tag.tag_name.toLowerCase().includes(tagSearchInput.toLowerCase()) &&
                            !selectedTags.includes(tag.tag_name)
                          )
                          return filtered.length > 0 ? (
                            filtered.map(tag => (
                              <div
                                key={tag.id}
                                onClick={() => {
                                  if (!selectedTags.includes(tag.tag_name)) {
                                    setSelectedTags([...selectedTags, tag.tag_name])
                                  }
                                  setTagSearchInput('')
                                  // Keep dropdown open and refocus input for continuous selection
                                  setTimeout(() => {
                                    setShowTagDropdown(true)
                                    tagInputRef.current?.focus()
                                  }, 0)
                                }}
                                className="px-3 py-2 hover:bg-gray-100 cursor-pointer text-sm"
                              >
                                {tag.tag_name}
                              </div>
                            ))
                          ) : (
                            <div className="px-3 py-2 text-gray-500 text-sm">
                              {tagSearchInput.trim() ? 'No matching tags found' : 'Start typing to search for tags'}
                            </div>
                          )
                        })()}
                      </div>
                    )}
                  </div>
                </div>
                <div>
                  <label htmlFor="match-mode-select" className="block text-sm font-medium text-gray-700 mb-1">
                    Match mode
                  </label>
                  <select
                    id="match-mode-select"
                    value={matchAll ? 'ALL' : 'ANY'}
                    onChange={(e) => setMatchAll(e.target.value === 'ALL')}
                    className="border rounded px-3 py-2"
                  >
                    <option value="ANY">Match any tag (photos with at least one selected tag)</option>
                    <option value="ALL">Match all tags (photos with all selected tags)</option>
                  </select>
                </div>
              </div>
            )}
          </div>
            )}
              </div>
            )}

            {/* Filters */}
            <div className="bg-gray-50 rounded-lg shadow py-2 px-4">
        <div className="flex items-center gap-2">
          <h2 className="text-sm font-medium text-gray-700">Additional filters</h2>
          <button
            onClick={() => setFiltersExpanded(!filtersExpanded)}
            className="text-lg text-gray-600 hover:text-gray-800"
            title={filtersExpanded ? 'Collapse filters section' : 'Expand filters section'}
            aria-label={filtersExpanded ? 'Collapse filters section' : 'Expand filters section'}
          >
            {filtersExpanded ? '▼' : '▶'}
          </button>
        </div>
        {filtersExpanded && (
          <div className="mt-3 space-y-2">
            <div className="flex items-end gap-4">
              <div>
                <label htmlFor="media-type-select" className="block text-sm font-medium text-gray-700 mb-1">
                  Media type
                </label>
                <select
                  id="media-type-select"
                  value={mediaType}
                  onChange={(e) => setMediaType(e.target.value)}
                  className="w-48 border rounded px-3 py-2"
                >
                  <option value="all">All media types</option>
                  <option value="image">Photos only</option>
                  <option value="video">Videos only</option>
                </select>
              </div>
              {searchType !== 'date' && (
                <>
                  <div>
                    <label htmlFor="date-taken-from-input" className="block text-sm font-medium text-gray-700 mb-1">
                      Date Taken - From
                    </label>
                    <input
                      id="date-taken-from-input"
                      type="date"
                      value={dateTakenFrom}
                      onChange={(e) => setDateTakenFrom(e.target.value)}
                      className="w-48 border rounded px-3 py-2"
                    />
                  </div>
                  <div>
                    <label htmlFor="date-taken-to-input" className="block text-sm font-medium text-gray-700 mb-1">
                      Date Taken - To <span className="text-gray-500 font-normal">(optional)</span>
                    </label>
                    <input
                      id="date-taken-to-input"
                      type="date"
                      value={dateTakenTo}
                      onChange={(e) => setDateTakenTo(e.target.value)}
                      className="w-48 border rounded px-3 py-2"
                    />
                  </div>
                  {(dateTakenFrom || dateTakenTo) && (
                    <div>
                      <label className="block text-sm font-medium text-gray-700 mb-1">
                        &nbsp;
                      </label>
                      <button
                        type="button"
                        onClick={() => {
                          setDateTakenFrom('')
                          setDateTakenTo('')
                        }}
                        className="px-3 py-2 text-sm text-gray-600 hover:text-gray-800 border rounded hover:bg-gray-50"
                        title="Clear date filters"
                      >
                        Clear dates
                      </button>
                    </div>
                  )}
                </>
              )}
            </div>
          </div>
            )}
            </div>

            {/* Search Button */}
            <div>
              <button
                onClick={handleSearch}
                disabled={loading}
                className="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
                aria-label="Search photos"
              >
                {loading ? 'Searching...' : 'Search photos'}
              </button>
            </div>
          </div>
        )}
      </div>

      {/* Results */}
      {results.length > 0 && (
        <div className="bg-white rounded-lg shadow p-4">
          <div className="sticky top-0 z-10 bg-white pb-4 mb-4 border-b">
            <div className="flex items-center justify-between">
              <div className="flex gap-2">
                <button
                  onClick={loadAllPhotos}
                  disabled={loadingAllPhotos || total === 0}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                  title="Open all photos in full-screen viewer"
                >
                  {loadingAllPhotos ? 'Loading...' : '▶ Play photos'}
                </button>
                <button
                  onClick={searchType === 'favorites' ? handleRemoveFromFavorites : handleAddToFavorites}
                  disabled={selectedPhotos.size === 0 || loadingFavorites}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                  title={searchType === 'favorites' ? 'Remove selected photos from favorites' : 'Add selected photos to favorites'}
                >
                  {loadingFavorites ? '...' : '⭐'}
                </button>
                <button
                  onClick={() => {
                    if (!canTagPhotos) {
                      return
                    }
                    setShowTagModal(true)
                  }}
                  disabled={selectedPhotos.size === 0 || !canTagPhotos}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                  title={
                    canTagPhotos
                      ? undefined
                      : 'Tagging requires permission for the Tag Photos feature'
                  }
                >
                  Tag selected photos
                </button>
                <button
                  onClick={() => {
                    if (!canDeletePhotos) {
                      return
                    }
                    handleDeleteSelectedPhotos()
                  }}
                  disabled={
                    selectedPhotos.size === 0 || deletingPhotos || !canDeletePhotos
                  }
                  className="px-3 py-1 text-sm border rounded text-red-700 border-red-200 hover:bg-red-50 disabled:bg-gray-100 disabled:text-gray-400 disabled:border-gray-200"
                  title={
                    canDeletePhotos
                      ? 'Permanently delete selected photos'
                      : 'Deleting requires permission for the Faces Maintenance feature'
                  }
                >
                  {deletingPhotos ? 'Deleting...' : '🗑 Delete selected'}
                </button>
                <button
                  onClick={selectAll}
                  disabled={results.length === 0}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                >
                  Select all
                </button>
                <button
                  onClick={clearAllSelected}
                  disabled={selectedPhotos.size === 0}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                >
                  Unselect All
                </button>
              </div>
            </div>
          </div>

          {/* Pagination - Top */}
          {total > pageSize && (
            <div className="mb-4 flex items-center justify-between border-b pb-4">
              <div className="text-sm text-gray-600">
                Page {page} of {Math.ceil(total / pageSize)}
              </div>
              <div className="flex gap-2">
                <button
                  onClick={() => {
                    const newPage = Math.max(1, page - 1)
                    setPage(newPage)
                    performSearch(newPage)
                  }}
                  disabled={page === 1}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                >
                  Previous
                </button>
                <button
                  onClick={() => {
                    const newPage = Math.min(Math.ceil(total / pageSize), page + 1)
                    setPage(newPage)
                    performSearch(newPage)
                  }}
                  disabled={page >= Math.ceil(total / pageSize)}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                >
                  Next
                </button>
              </div>
            </div>
          )}

          {/* Results Table */}
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="border-b">
                  <th className="text-left p-2 w-12">☑</th>
                  {searchType === 'name' && (
                    <th
                      className="text-left p-2 cursor-pointer hover:bg-gray-50"
                      onClick={() => handleSort('person')}
                    >
                      Person {sortColumn === 'person' && (sortDir === 'asc' ? '↑' : '↓')}
                    </th>
                  )}
                  <th
                    className="text-left p-2 cursor-pointer hover:bg-gray-50"
                    onClick={() => handleSort('tags')}
                  >
                    Tags {sortColumn === 'tags' && (sortDir === 'asc' ? '↑' : '↓')}
                  </th>
                  {searchType !== 'name' && (
                    <th
                      className="text-left p-2 cursor-pointer hover:bg-gray-50"
                      onClick={() => handleSort('processed')}
                    >
                      Processed {sortColumn === 'processed' && (sortDir === 'asc' ? '↑' : '↓')}
                    </th>
                  )}
                  <th className="text-left p-2 w-12">⭐</th>
                  <th className="text-left p-2 w-12">📁</th>
                  {searchType !== 'no_faces' && (
                    <th className="text-left p-2 w-12">👤</th>
                  )}
                  <th
                    className="text-left p-2 cursor-pointer hover:bg-gray-50"
                    onClick={() => handleSort('path')}
                  >
                    Photo path {sortColumn === 'path' && (sortDir === 'asc' ? '↑' : '↓')}
                  </th>
                  <th
                    className="text-left p-2 cursor-pointer hover:bg-gray-50"
                    onClick={() => handleSort('date_taken')}
                  >
                    Date Taken {sortColumn === 'date_taken' && (sortDir === 'asc' ? '↑' : '↓')}
                  </th>
                </tr>
              </thead>
              <tbody>
                {sortedResults.map(photo => (
                  <tr key={photo.id} className="border-b hover:bg-gray-50">
                    <td className="p-2">
                      <input
                        type="checkbox"
                        checked={selectedPhotos.has(photo.id)}
                        onChange={() => toggleSelection(photo.id)}
                        className="cursor-pointer"
                      />
                    </td>
                    {searchType === 'name' && (
                      <td className="p-2">{photo.person_name || ''}</td>
                    )}
                    <td className="p-2" title={photo.tags.join(', ')}>
                      {photo.tags.length > 0 ? photo.tags.join(', ') : 'No tags'}
                    </td>
                    {searchType !== 'name' && (
                      <td className="p-2 text-center">{photo.processed ? 'Yes' : 'No'}</td>
                    )}
                    <td className="p-2 text-center">
                      {photo.is_favorite && (
                        <button
                          onClick={(e) => {
                            e.preventDefault()
                            e.stopPropagation()
                            handleToggleFavorite(photo.id)
                          }}
                          className="cursor-pointer hover:text-yellow-600 text-lg"
                          title="Remove from favorites"
                        >
                          ⭐
                        </button>
                      )}
                    </td>
                    <td className="p-2">
                      <button
                        onClick={(e) => {
                          e.preventDefault()
                          e.stopPropagation()
                          openFolder(photo.id)
                        }}
                        className="cursor-pointer hover:text-blue-600 text-lg"
                        title="Open folder in file manager"
                      >
                        📁
                      </button>
                    </td>
                    {searchType !== 'no_faces' && (
                      <td className="p-2">
                        {photo.has_faces && (
                          <span title={`${photo.face_count} face(s)`}>👤</span>
                        )}
                      </td>
                    )}
                    <td className="p-2">
                      <button
                        onClick={() => openPhoto(photo.id)}
                        className="text-blue-600 hover:underline cursor-pointer"
                        title="Open photo"
                      >
                        {photo.path}
                      </button>
                    </td>
                    <td className="p-2">{photo.date_taken || 'No date'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          {/* Pagination */}
          {total > pageSize && (
            <div className="mt-4 flex items-center justify-between">
              <div className="text-sm text-gray-600">
                Page {page} of {Math.ceil(total / pageSize)}
              </div>
              <div className="flex gap-2">
                <button
                  onClick={() => {
                    const newPage = Math.max(1, page - 1)
                    setPage(newPage)
                    performSearch(newPage)
                  }}
                  disabled={page === 1}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                >
                  Previous
                </button>
                <button
                  onClick={() => {
                    const newPage = Math.min(Math.ceil(total / pageSize), page + 1)
                    setPage(newPage)
                    performSearch(newPage)
                  }}
                  disabled={page >= Math.ceil(total / pageSize)}
                  className="px-3 py-1 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
                >
                  Next
                </button>
              </div>
            </div>
          )}
        </div>
      )}

      {/* Delete Confirmation Dialog */}
      {showDeleteConfirm && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-[60]">
          <div className="bg-white rounded-lg shadow-xl w-full max-w-md p-6">
            <h3 className="text-lg font-bold mb-4">Confirm Delete</h3>
            <p className="text-gray-700 mb-6">
              Remove {selectedTagIds.size} tag(s) ({selectedTagNames}) from {selectedPhotos.size} photo(s)?
            </p>
            <div className="flex justify-end gap-3">
              <button
                onClick={() => setShowDeleteConfirm(false)}
                className="px-4 py-2 bg-gray-100 text-gray-700 rounded hover:bg-gray-200"
              >
                Cancel
              </button>
              <button
                onClick={confirmDeleteTags}
                className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
              >
                Delete
              </button>
            </div>
          </div>
        </div>
      )}

      {/* Tag Modal */}
      {showTagModal && (
        <div className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50">
          <div className="bg-white rounded-lg shadow-xl w-full max-w-lg max-h-[80vh] flex flex-col">
            <div className="p-4 border-b">
              <h2 className="text-xl font-bold">Tag Selected Photos</h2>
              <p className="text-sm text-gray-600 mt-1">
                {selectedPhotos.size} photo(s) selected
              </p>
            </div>
            <div className="p-4 flex-1 overflow-auto">
              <div className="mb-4">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Select Existing Tag:
                </label>
                <select
                  value={selectedTagName}
                  onChange={(e) => {
                    const tagName = e.target.value
                    if (tagName) {
                      // Immediately add the tag and clear the dropdown
                      handleSelectExistingTag(tagName)
                    }
                  }}
                  className="w-full px-3 py-2 border border-gray-300 rounded"
                >
                  <option value="">Select tag...</option>
                  {availableTags.map(tag => (
                    <option key={tag.id} value={tag.tag_name}>
                      {tag.tag_name}
                    </option>
                  ))}
                </select>
                <p className="text-xs text-gray-500 mt-1">
                  Selecting a tag will immediately add it to the photos. You can select multiple tags in a row.
                </p>
              </div>
              <div className="mb-4">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Enter New Tag Name:
                </label>
                <input
                  type="text"
                  value={newTagName}
                  onChange={(e) => {
                    setNewTagName(e.target.value)
                  }}
                  className="w-full px-3 py-2 border border-gray-300 rounded"
                  placeholder="Type new tag name..."
                  onKeyDown={(e) => {
                    if (e.key === 'Enter') {
                      handleAddTag()
                    }
                  }}
                />
                <p className="text-xs text-gray-500 mt-1">
                  You can select an existing tag and enter a new tag name to add both at once. New tags will be created in the database automatically.
                </p>
              </div>
              
              <div className="mb-4 border-t pt-4">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Tags (present in all selected photos):
                </label>
                {loadingTags ? (
                  <p className="text-sm text-gray-500">Loading tags...</p>
                ) : allPhotoTags.length === 0 ? (
                  <p className="text-sm text-gray-500">No removable tags on selected photos</p>
                ) : (
                  <div className="space-y-2 max-h-40 overflow-y-auto border rounded p-2">
                    {allPhotoTags.map(tag => (
                      <div key={tag.tag_id} className="flex items-center gap-2 py-1">
                        <input
                          type="checkbox"
                          checked={selectedTagIds.has(tag.tag_id)}
                          onChange={(e) => {
                            const newSet = new Set(selectedTagIds)
                            if (e.target.checked) {
                              newSet.add(tag.tag_id)
                            } else {
                              newSet.delete(tag.tag_id)
                            }
                            setSelectedTagIds(newSet)
                          }}
                          className="w-4 h-4"
                        />
                        <span className="flex-1 text-sm">
                          {tag.tag_name}
                        </span>
                      </div>
                    ))}
                  </div>
                )}
              </div>
            </div>
            <div className="p-4 border-t flex justify-between">
              <div className="flex gap-2">
                <button
                  onClick={handleDeleteTags}
                  disabled={selectedTagIds.size === 0}
                  className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
                >
                  Delete Selected Tags
                </button>
              </div>
              <div className="flex gap-2">
                <button
                  onClick={() => {
                    setShowTagModal(false)
                    setSelectedTagName('')
                    setNewTagName('')
                    setSelectedTagIds(new Set())
                    setSelectedPhotos(new Set()) // Unselect all photos
                    // Reload search results when closing dialog
                    performSearch(page)
                  }}
                  className="px-4 py-2 bg-gray-100 text-gray-700 rounded hover:bg-gray-200"
                >
                  Close
                </button>
                <button
                  onClick={handleAddTag}
                  disabled={!selectedTagName.trim() && !newTagName.trim()}
                  className="px-4 py-2 bg-indigo-600 text-white rounded hover:bg-indigo-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
                >
                  Add Tag
                </button>
              </div>
            </div>
          </div>
        </div>
      )}

      {/* Photo Viewer */}
      {showPhotoViewer && allPhotos.length > 0 && (
        <PhotoViewer
          photos={allPhotos}
          initialIndex={photoViewerIndex}
          onClose={() => setShowPhotoViewer(false)}
        />
      )}
    </div>
  )
}
