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: 'Search photos by name' },
  { value: 'date', label: 'Search photos by date' },
  { value: 'tags', label: 'Search photos by tags' },
  { value: 'no_faces', label: 'Photos without faces' },
  { value: 'no_tags', label: 'Photos without tags' },
  { value: 'processed', label: 'Search processed photos' },
  { value: 'unprocessed', label: 'Search un-processed 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 [personName, setPersonName] = useState('')
  const [selectedTags, setSelectedTags] = useState<string[]>([])
  const [matchAll, setMatchAll] = useState(false)
  const [dateFrom, setDateFrom] = useState('')
  const [dateTo, setDateTo] = 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[]>([])
  
  // 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)
    }
  }

  useEffect(() => {
    loadTags()
    loadAllPeople()
  }, [])

  const performSearch = async (pageNum: number = page) => {
    setLoading(true)
    try {
      const params: any = {
        search_type: searchType,
        page: pageNum,
        page_size: pageSize,
      }

      // For "Photos without faces" search, always exclude videos
      if (searchType === '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 (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) {
          alert('Please enter at least one name or select a person to search.')
          setLoading(false)
          return
        }
        params.person_name = allNames.join(', ')
      } else if (searchType === 'date') {
        if (!dateFrom && !dateTo) {
          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
      } else if (searchType === 'tags') {
        if (selectedTags.length === 0) {
          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) {
      console.error('Error searching photos:', error)
      alert('Error searching photos. Please try again.')
    } finally {
      setLoading(false)
    }
  }

  const handleSearch = () => {
    setPage(1)
    setSelectedPhotos(new Set())
    performSearch(1)
  }

  // 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(() => {
    // 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 search
    if (searchType !== 'tags') {
      setSelectedTags([])
    }
    // Clear person autocomplete when switching away from name search
    if (searchType !== 'name') {
      setSelectedPeople([])
      setInputValue('')
      setPersonName('')
    }
    // 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 handleAddTag = async () => {
    if (selectedPhotos.size === 0) {
      alert('Please select photos to tag.')
      return
    }
    
    // Determine which tag to use: new tag input or selected from dropdown
    const tagToAdd = newTagName.trim() || selectedTagName.trim()
    
    if (!tagToAdd) {
      alert('Please select a tag or enter a new tag name.')
      return
    }
    
    try {
      // If it's a new tag (from input field), create it first
      if (newTagName.trim()) {
        await tagsApi.create(newTagName.trim())
        // Refresh available tags list
        await loadTags()
        // Clear the new tag input
        setNewTagName('')
      }
      
      // Add tag to photos
      await tagsApi.addToPhotos({
        photo_ids: Array.from(selectedPhotos),
        tag_names: [tagToAdd],
      })
      
      setSelectedTagName('')
      // 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(', ')
        }
      } else if (searchType === 'date') {
        baseParams.date_from = dateFrom || undefined
        baseParams.date_to = dateTo || undefined
      } else 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 Configuration</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 w-1/3">
              <div className="flex items-center gap-2">
                <label className="text-sm font-medium text-gray-700">
                  Search type:
                </label>
                <select
                  value={searchType}
                  onChange={(e) => setSearchType(e.target.value as SearchType)}
                  className="w-64 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' ? 'w-full' : 'w-1/3'}`}>
          {searchType === 'name' && (
          <div className="space-y-2">
            <label className="text-sm font-medium text-gray-700">
              Person name(s):
            </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"
                      >
                        ×
                      </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 results"
                >
                  Clear all
                </button>
              </div>
            )}
            
            {/* Input with dropdown */}
            <div className="relative">
              <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 to search or select people..."
              />
              
              {/* 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' : 'No people available'}
                    </div>
                  )}
                </div>
              )}
            </div>
            
            <p className="text-xs text-gray-500">
              Select people from dropdown or type names manually (comma-separated)
            </p>
          </div>
        )}
        
        {searchType === 'date' && (
          <div className="space-y-2">
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-1">
                From date:
              </label>
              <input
                type="date"
                value={dateFrom}
                onChange={(e) => setDateFrom(e.target.value)}
                className="w-48 border rounded px-3 py-2"
                placeholder="YYYY-MM-DD"
              />
            </div>
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-1">
                To date:
              </label>
              <input
                type="date"
                value={dateTo}
                onChange={(e) => setDateTo(e.target.value)}
                className="w-48 border rounded px-3 py-2"
                placeholder="YYYY-MM-DD (optional)"
              />
            </div>
          </div>
        )}
        
        {searchType === 'tags' && (
          <div>
            <div className="flex items-center gap-2">
              <h2 className="text-sm font-medium text-gray-700">Tags</h2>
              <button
                onClick={() => setTagsExpanded(!tagsExpanded)}
                className="text-lg text-gray-600 hover:text-gray-800"
                title={tagsExpanded ? 'Collapse' : 'Expand'}
              >
                {tagsExpanded ? '▼' : '▶'}
              </button>
            </div>
            {tagsExpanded && (
              <div className="mt-3 space-y-2">
                <div>
                  <select
                    multiple
                    value={selectedTags}
                    onChange={(e) => {
                      const selected = Array.from(e.target.selectedOptions, option => option.value)
                      setSelectedTags(selected)
                    }}
                    className="w-full border rounded px-3 py-2 min-h-[120px]"
                    size={Math.min(availableTags.length, 8)}
                  >
                    {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">
                    Hold Ctrl/Cmd to select multiple tags
                  </p>
                </div>
                <div>
                  <label className="block text-sm font-medium text-gray-700 mb-1">
                    Match mode:
                  </label>
                  <select
                    value={matchAll ? 'ALL' : 'ANY'}
                    onChange={(e) => setMatchAll(e.target.value === 'ALL')}
                    className="border rounded px-3 py-2"
                  >
                    <option value="ANY">ANY (photos with any tag)</option>
                    <option value="ALL">ALL (photos with all tags)</option>
                  </select>
                </div>
              </div>
            )}
          </div>
            )}
              </div>
            )}

            {/* Filters */}
            <div className="bg-gray-50 rounded-lg shadow py-2 px-4 w-1/3">
        <div className="flex items-center gap-2">
          <h2 className="text-sm font-medium text-gray-700">Filters</h2>
          <button
            onClick={() => setFiltersExpanded(!filtersExpanded)}
            className="text-lg text-gray-600 hover:text-gray-800"
            title={filtersExpanded ? 'Collapse' : 'Expand'}
          >
            {filtersExpanded ? '▼' : '▶'}
          </button>
        </div>
        {filtersExpanded && (
          <div className="mt-3 space-y-2">
            <div>
              <label className="block text-sm font-medium text-gray-700 mb-1">
                Media Type:
              </label>
              <select
                value={mediaType}
                onChange={(e) => setMediaType(e.target.value)}
                className="w-48 border rounded px-3 py-2"
              >
                <option value="all">All</option>
                <option value="image">Photos</option>
                <option value="video">Videos</option>
              </select>
            </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"
              >
                {loading ? 'Searching...' : 'Search'}
              </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>

          {/* 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) => {
                    setSelectedTagName(e.target.value)
                    // Clear new tag input when selecting from dropdown
                    if (e.target.value) {
                      setNewTagName('')
                    }
                  }}
                  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>
              </div>
              <div className="mb-4">
                <label className="block text-sm font-medium text-gray-700 mb-2">
                  Or Enter New Tag Name:
                </label>
                <input
                  type="text"
                  value={newTagName}
                  onChange={(e) => {
                    setNewTagName(e.target.value)
                    // Clear selected tag when typing new tag
                    if (e.target.value) {
                      setSelectedTagName('')
                    }
                  }}
                  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">
                  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>
  )
}
