import { useState, useEffect, useCallback, useRef } from 'react'
import { Star, Check, X, RefreshCw } from 'lucide-react'
import clsx from 'clsx'
import { photos as photosApi } from '../../services/api'

// Auto-retry schedule (ms). Backend generates thumbs on-demand via Celery, so
// first hit often 404s. Try a few times with backoff before giving up.
const AUTO_RETRY_DELAYS = [1500, 3500, 6000]

interface Photo {
  id: string
  filepath: string
  filename: string
  width: number | null
  height: number | null
  taken_at: string | null
  rating: number
  is_picked: boolean
  is_rejected: boolean
  file_hash: string
  media_type: string
}

interface PhotoThumbnailProps {
  photo: Photo
  size: number
  isSelected: boolean
  onClick: (e: React.MouseEvent) => void
}

export function PhotoThumbnail({ photo, size, isSelected, onClick }: PhotoThumbnailProps) {
  const [imageError, setImageError] = useState(false)
  const [imageLoaded, setImageLoaded] = useState(false)
  const [retryCount, setRetryCount] = useState(0)
  const [isRetrying, setIsRetrying] = useState(false)
  const retryTimerRef = useRef<number | null>(null)

  // Cache-bust on retry so the browser actually re-requests instead of
  // serving the cached 404.
  const baseUrl = photosApi.getThumbnailUrl(photo.id, 'medium')
  const thumbnailUrl = retryCount > 0 ? `${baseUrl}?retry=${retryCount}` : baseUrl

  // Calculate aspect ratio for proper sizing (default to 1:1 if dimensions unknown)
  const aspectRatio = (photo.height && photo.width) ? photo.height / photo.width : 1
  const displayHeight = size * Math.min(aspectRatio, 1.5) // Cap height at 1.5x width

  const clearRetryTimer = () => {
    if (retryTimerRef.current !== null) {
      window.clearTimeout(retryTimerRef.current)
      retryTimerRef.current = null
    }
  }

  const handleImageLoad = () => {
    setImageLoaded(true)
    setIsRetrying(false)
  }

  const handleImageError = () => {
    // Schedule next auto-retry if attempts remain.
    const nextDelay = AUTO_RETRY_DELAYS[retryCount]
    if (nextDelay !== undefined) {
      setIsRetrying(true)
      clearRetryTimer()
      retryTimerRef.current = window.setTimeout(() => {
        retryTimerRef.current = null
        setRetryCount(prev => prev + 1)
      }, nextDelay)
    } else {
      setImageError(true)
      setIsRetrying(false)
    }
  }

  const handleManualRetry = useCallback((e: React.MouseEvent) => {
    e.stopPropagation() // Prevent selection when clicking retry
    clearRetryTimer()
    setRetryCount(prev => prev + 1)
    setImageError(false)
    setImageLoaded(false)
    setIsRetrying(true)
  }, [])

  // Reset state when photo changes (component is reused across rows when virtualized)
  useEffect(() => {
    clearRetryTimer()
    setImageError(false)
    setImageLoaded(false)
    setRetryCount(0)
    setIsRetrying(false)
  }, [photo.id])

  // Clear pending timer on unmount to avoid setState-after-unmount.
  useEffect(() => {
    return () => clearRetryTimer()
  }, [])
  
  return (
    <div
      className={clsx(
        'group relative cursor-pointer overflow-hidden rounded-sm transition-all duration-200',
        'hover:ring-2 hover:ring-primary/50',
        isSelected && 'ring-2 ring-primary shadow-lg',
        !imageLoaded && 'bg-surface animate-pulse'
      )}
      style={{
        width: size,
        height: displayHeight,
      }}
      onClick={onClick}
      title="Click to select • Shift+Click for range • Ctrl+Click to add"
    >
      {/* Thumbnail Image */}
      {!imageError ? (
        <>
          <img
            src={thumbnailUrl}
            alt={photo.filename}
            className={clsx(
              'h-full w-full object-cover transition-opacity duration-200',
              imageLoaded ? 'opacity-100' : 'opacity-0'
            )}
            onLoad={handleImageLoad}
            onError={handleImageError}
            loading="lazy"
          />
          {/* Loading indicator */}
          {!imageLoaded && (
            <div className="absolute inset-0 flex items-center justify-center bg-surface">
              <div className="text-text-muted">
                {isRetrying ? (
                  <div className="text-center">
                    <RefreshCw className="h-5 w-5 animate-spin mx-auto mb-1" />
                    <div className="text-xs">Retrying...</div>
                  </div>
                ) : (
                  <div className="h-8 w-8 border-2 border-primary/30 border-t-primary rounded-full animate-spin" />
                )}
              </div>
            </div>
          )}
        </>
      ) : (
        <div className="flex h-full w-full items-center justify-center bg-surface text-text-muted">
          <div className="text-center text-xs">
            <button
              onClick={handleManualRetry}
              className="p-2 hover:bg-surface-light rounded transition-colors"
              title="Retry loading thumbnail"
            >
              <RefreshCw className="h-5 w-5 mb-1" />
            </button>
            <div>Unable to load</div>
            <div className="mt-1 font-mono text-[10px] px-2 break-all">{photo.filename}</div>
          </div>
        </div>
      )}
      
      {/* Selection Indicator */}
      {isSelected && (
        <div className="absolute left-1 top-1 flex h-6 w-6 items-center justify-center rounded-full bg-primary text-white">
          <Check className="h-4 w-4" />
        </div>
      )}
      
      {/* Rating Stars */}
      {photo.rating > 0 && (
        <div className="absolute bottom-1 left-1 flex gap-0.5">
          {Array.from({ length: photo.rating }).map((_, i) => (
            <Star
              key={i}
              className="h-3 w-3 fill-star text-star"
            />
          ))}
        </div>
      )}
      
      {/* Flag Indicators */}
      <div className="absolute bottom-1 right-1">
        {photo.is_picked && (
          <Check className="h-4 w-4 text-pick" />
        )}
        {photo.is_rejected && (
          <X className="h-4 w-4 text-reject" />
        )}
      </div>
      
      {/* File Type Badge for RAW/Video */}
      {(photo.filepath.toLowerCase().match(/\.(raw|arw|cr2|cr3|nef|orf|rw2|dng)$/i) ||
        photo.filepath.toLowerCase().match(/\.(mov|mp4|avi|mkv)$/i)) && (
        <div className="absolute right-1 top-1 rounded bg-black/50 px-1 py-0.5 text-[10px] font-medium text-white">
          {photo.filepath.toLowerCase().match(/\.(mov|mp4|avi|mkv)$/i) ? 'VIDEO' : 'RAW'}
        </div>
      )}
    </div>
  )
}