import { useEffect, useState, useMemo } from 'react'
import facesApi, { MaintenanceFaceItem } from '../api/faces'
import { apiClient } from '../api/client'

type SortColumn = 'person_name' | 'quality' | 'photo_path' | 'excluded'
type SortDir = 'asc' | 'desc'
type ExcludedFilter = 'all' | 'excluded' | 'included'
type IdentifiedFilter = 'all' | 'identified' | 'unidentified'

export default function FacesMaintenance() {
  const [faces, setFaces] = useState<MaintenanceFaceItem[]>([])
  const [total, setTotal] = useState(0)
  const [pageSize, setPageSize] = useState(50)
  const [minQuality, setMinQuality] = useState(0.0)
  const [maxQuality, setMaxQuality] = useState(1.0)
  const [excludedFilter, setExcludedFilter] = useState<ExcludedFilter>('all')
  const [identifiedFilter, setIdentifiedFilter] = useState<IdentifiedFilter>('all')
  const [selectedFaces, setSelectedFaces] = useState<Set<number>>(new Set())
  const [loading, setLoading] = useState(false)
  const [deleting, setDeleting] = useState(false)
  const [excluding, setExcluding] = useState(false)
  const [showDeleteConfirm, setShowDeleteConfirm] = useState(false)
  const [sortColumn, setSortColumn] = useState<SortColumn | null>(null)
  const [sortDir, setSortDir] = useState<SortDir>('asc')

  const loadFaces = async () => {
    setLoading(true)
    try {
      const res = await facesApi.getMaintenanceFaces({
        page: 1,
        page_size: pageSize,
        min_quality: minQuality,
        max_quality: maxQuality,
        excluded_filter: excludedFilter,
        identified_filter: identifiedFilter,
      })
      setFaces(res.items)
      setTotal(res.total)
      setSelectedFaces(new Set()) // Clear selection when reloading
    } catch (error) {
      console.error('Error loading faces:', error)
      alert('Error loading faces. Please try again.')
    } finally {
      setLoading(false)
    }
  }

  useEffect(() => {
    loadFaces()
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [pageSize, minQuality, maxQuality, excludedFilter, identifiedFilter])

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

  const selectAll = () => {
    setSelectedFaces(new Set(sortedFaces.map(f => f.id)))
  }

  const unselectAll = () => {
    setSelectedFaces(new Set())
  }

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

  const sortedFaces = useMemo(() => {
    if (!sortColumn) return faces

    return [...faces].sort((a, b) => {
      let aVal: any
      let bVal: any

      switch (sortColumn) {
        case 'person_name':
          aVal = a.person_name || 'Unidentified'
          bVal = b.person_name || 'Unidentified'
          break
        case 'quality':
          aVal = a.quality_score
          bVal = b.quality_score
          break
        case 'photo_path':
          aVal = a.photo_path
          bVal = b.photo_path
          break
        case 'excluded':
          aVal = a.excluded ? 1 : 0
          bVal = b.excluded ? 1 : 0
          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
    })
  }, [faces, sortColumn, sortDir])

  const handleDelete = async () => {
    if (selectedFaces.size === 0) {
      alert('Please select at least one face to delete.')
      return
    }
    setShowDeleteConfirm(true)
  }

  const confirmDelete = async () => {
    setShowDeleteConfirm(false)
    setDeleting(true)
    try {
      await facesApi.deleteFaces({
        face_ids: Array.from(selectedFaces),
      })
      // Reload faces after deletion
      await loadFaces()
      alert(`Successfully deleted ${selectedFaces.size} face(s)`)
    } catch (error) {
      console.error('Error deleting faces:', error)
      alert('Error deleting faces. Please try again.')
    } finally {
      setDeleting(false)
    }
  }

  const handleExclude = async () => {
    if (selectedFaces.size === 0) {
      alert('Please select at least one face to exclude.')
      return
    }
    setExcluding(true)
    try {
      const faceIds = Array.from(selectedFaces)
      // Exclude each selected face
      await Promise.all(faceIds.map(faceId => facesApi.setExcluded(faceId, true)))
      // Reload faces after exclusion
      await loadFaces()
      alert(`Successfully excluded ${selectedFaces.size} face(s)`)
    } catch (error) {
      console.error('Error excluding faces:', error)
      alert('Error excluding faces. Please try again.')
    } finally {
      setExcluding(false)
    }
  }

  return (
    <div>

      {/* Controls */}
      <div className="bg-white rounded-lg shadow mb-4 p-4">
        <div className="grid grid-cols-5 gap-4">
          {/* Quality Range Selector */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Quality Range
            </label>
            <div className="flex items-center gap-2">
              <input
                type="range"
                min={0}
                max={1}
                step={0.01}
                value={minQuality}
                onChange={(e) => setMinQuality(parseFloat(e.target.value))}
                className="flex-1"
              />
              <input
                type="range"
                min={0}
                max={1}
                step={0.01}
                value={maxQuality}
                onChange={(e) => setMaxQuality(parseFloat(e.target.value))}
                className="flex-1"
              />
            </div>
            <div className="flex justify-between text-xs text-gray-500 mt-1">
              <span>Min: {(minQuality * 100).toFixed(0)}%</span>
              <span>Max: {(maxQuality * 100).toFixed(0)}%</span>
            </div>
          </div>

          {/* Excluded Faces Filter */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Excluded Faces
            </label>
            <select
              value={excludedFilter}
              onChange={(e) => setExcludedFilter(e.target.value as ExcludedFilter)}
              className="block w-auto border rounded px-2 py-1 text-sm"
            >
              <option value="all">All</option>
              <option value="excluded">Excluded only</option>
              <option value="included">Included only</option>
            </select>
          </div>

          {/* Identified Filter */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Identified
            </label>
            <select
              value={identifiedFilter}
              onChange={(e) => setIdentifiedFilter(e.target.value as IdentifiedFilter)}
              className="block w-auto border rounded px-2 py-1 text-sm"
            >
              <option value="all">All</option>
              <option value="identified">Identified only</option>
              <option value="unidentified">Unidentified only</option>
            </select>
          </div>

          {/* Batch Size */}
          <div>
            <label className="block text-sm font-medium text-gray-700 mb-2">
              Batch Size
            </label>
            <select
              value={pageSize}
              onChange={(e) => setPageSize(parseInt(e.target.value))}
              className="block w-auto border rounded px-2 py-1 text-sm"
            >
              {[25, 50, 100, 200, 500, 1000, 1500, 2000].map((n) => (
                <option key={n} value={n}>
                  {n}
                </option>
              ))}
            </select>
          </div>

          {/* Action Buttons */}
          <div className="flex items-end gap-2">
            <button
              onClick={selectAll}
              disabled={faces.length === 0}
              className="px-3 py-2 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
            >
              Select All
            </button>
            <button
              onClick={unselectAll}
              disabled={selectedFaces.size === 0}
              className="px-3 py-2 text-sm border rounded hover:bg-gray-50 disabled:bg-gray-100 disabled:text-gray-400"
            >
              Unselect All
            </button>
            <button
              onClick={handleExclude}
              disabled={selectedFaces.size === 0 || excluding}
              className="px-3 py-2 text-sm bg-orange-600 text-white rounded hover:bg-orange-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
            >
              {excluding ? 'Excluding...' : 'Exclude Selected'}
            </button>
            <button
              onClick={handleDelete}
              disabled={selectedFaces.size === 0 || deleting}
              className="px-3 py-2 text-sm bg-red-600 text-white rounded hover:bg-red-700 disabled:bg-gray-400 disabled:cursor-not-allowed"
            >
              {deleting ? 'Deleting...' : 'Delete Selected'}
            </button>
          </div>
        </div>
      </div>

      {/* Results */}
      <div className="bg-white rounded-lg shadow p-4">
        <div className="mb-4">
          <span className="text-sm font-medium text-gray-700">
            Total: {total} face(s)
          </span>
          {selectedFaces.size > 0 && (
            <span className="ml-4 text-sm text-gray-600">
              Selected: {selectedFaces.size} face(s)
            </span>
          )}
        </div>

        {loading ? (
          <div className="text-center py-8 text-gray-500">Loading faces...</div>
        ) : sortedFaces.length === 0 ? (
          <div className="text-center py-8 text-gray-500">No faces found</div>
        ) : (
          <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>
                  <th className="text-left p-2 w-24">Thumbnail</th>
                  <th
                    className="text-left p-2 cursor-pointer hover:bg-gray-50"
                    onClick={() => handleSort('person_name')}
                  >
                    Person Name {sortColumn === 'person_name' && (sortDir === 'asc' ? '↑' : '↓')}
                  </th>
                  <th
                    className="text-left p-2 cursor-pointer hover:bg-gray-50"
                    onClick={() => handleSort('photo_path')}
                  >
                    File Path {sortColumn === 'photo_path' && (sortDir === 'asc' ? '↑' : '↓')}
                  </th>
                  <th
                    className="text-left p-2 cursor-pointer hover:bg-gray-50"
                    onClick={() => handleSort('quality')}
                  >
                    Quality {sortColumn === 'quality' && (sortDir === 'asc' ? '↑' : '↓')}
                  </th>
                  <th
                    className="text-left p-2 cursor-pointer hover:bg-gray-50"
                    onClick={() => handleSort('excluded')}
                  >
                    Excluded {sortColumn === 'excluded' && (sortDir === 'asc' ? '↑' : '↓')}
                  </th>
                </tr>
              </thead>
              <tbody>
                {sortedFaces.map((face) => (
                  <tr key={face.id} className="border-b hover:bg-gray-50">
                    <td className="p-2">
                      <input
                        type="checkbox"
                        checked={selectedFaces.has(face.id)}
                        onChange={() => toggleSelection(face.id)}
                        className="cursor-pointer"
                      />
                    </td>
                    <td className="p-2">
                      <div
                        className="w-20 h-20 bg-gray-100 rounded overflow-hidden flex items-center justify-center relative group cursor-pointer"
                        onClick={() => {
                          const photoUrl = `${apiClient.defaults.baseURL}/api/v1/photos/${face.photo_id}/image`
                          window.open(photoUrl, '_blank')
                        }}
                        title="Click to open full photo"
                      >
                        <img
                          src={`${apiClient.defaults.baseURL}/api/v1/faces/${face.id}/crop`}
                          alt={`Face ${face.id}`}
                          className="max-w-full max-h-full object-contain pointer-events-none"
                          crossOrigin="anonymous"
                          loading="lazy"
                          onError={(e) => {
                            const target = e.target as HTMLImageElement
                            target.style.display = 'none'
                            const parent = target.parentElement
                            if (parent && !parent.querySelector('.error-fallback')) {
                              const fallback = document.createElement('div')
                              fallback.className = 'text-gray-400 text-xs error-fallback'
                              fallback.textContent = `#${face.id}`
                              parent.appendChild(fallback)
                            }
                          }}
                        />
                        <div className="absolute inset-0 bg-black bg-opacity-0 group-hover:bg-opacity-10 transition-opacity pointer-events-none" />
                      </div>
                    </td>
                    <td className="p-2">
                      {face.person_name || (
                        <span className="text-gray-400 italic">Unidentified</span>
                      )}
                    </td>
                    <td className="p-2">
                      <span className="text-blue-600" title={face.photo_path}>
                        {face.photo_path}
                      </span>
                    </td>
                    <td className="p-2">
                      {(face.quality_score * 100).toFixed(1)}%
                    </td>
                    <td className="p-2">
                      {face.excluded ? (
                        <span className="text-red-600 font-medium">Yes</span>
                      ) : (
                        <span className="text-gray-500">No</span>
                      )}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        )}
      </div>

      {/* Delete Confirmation Dialog */}
      {showDeleteConfirm && (
        <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-md p-6">
            <h3 className="text-lg font-bold mb-4">Confirm Delete</h3>
            <p className="text-gray-700 mb-6">
              Are you sure you want to delete {selectedFaces.size} face(s) from
              the database? This action cannot be undone.
            </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={confirmDelete}
                className="px-4 py-2 bg-red-600 text-white rounded hover:bg-red-700"
              >
                Delete
              </button>
            </div>
          </div>
        </div>
      )}
    </div>
  )
}

