'use client';

import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
import { useRouter } from 'next/navigation';
import { useSession } from 'next-auth/react';
import { Photo, Person } from '@prisma/client';
import Image from 'next/image';
import { Check, Flag, Play, Heart, Download } from 'lucide-react';
import { Button } from '@/components/ui/button';
import {
  TooltipProvider,
  TooltipContent,
  TooltipTrigger,
} from '@/components/ui/tooltip';
import * as TooltipPrimitive from '@radix-ui/react-tooltip';
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { parseFaceLocation, isPointInFace } from '@/lib/face-utils';
import { isUrl, isVideo, getImageSrc } from '@/lib/photo-utils';
import { LoginDialog } from '@/components/LoginDialog';
import { RegisterDialog } from '@/components/RegisterDialog';

interface FaceWithLocation {
  id: number;
  personId: number | null;
  location: string;
  person: Person | null;
}

interface PhotoWithPeople extends Photo {
  faces?: FaceWithLocation[];
}

interface PhotoGridProps {
  photos: PhotoWithPeople[];
  selectionMode?: boolean;
  selectedPhotoIds?: number[];
  onToggleSelect?: (photoId: number) => void;
  refreshFavoritesKey?: number;
}


/**
 * Gets unique people names from photo faces
 */
function getPeopleNames(photo: PhotoWithPeople): string[] {
  if (!photo.faces) return [];
  
  const people = photo.faces
    .map((face) => face.person)
    .filter((person): person is Person => person !== null)
    .map((person: any) => {
      // Handle both camelCase and snake_case
      const firstName = person.firstName || person.first_name || '';
      const lastName = person.lastName || person.last_name || '';
      return `${firstName} ${lastName}`.trim();
    });
  
  // Remove duplicates
  return Array.from(new Set(people));
}

const REPORT_COMMENT_MAX_LENGTH = 300;

const getPhotoFilename = (photo: Photo) => {
  if (photo?.filename) {
    return photo.filename;
  }

  if (photo?.path) {
    const segments = photo.path.split(/[/\\]/);
    const lastSegment = segments.pop();
    if (lastSegment) {
      return lastSegment;
    }
  }

  return `photo-${photo?.id ?? 'download'}.jpg`;
};

const getPhotoDownloadUrl = (
  photo: Photo,
  options?: { forceProxy?: boolean; watermark?: boolean }
) => {
  const path = photo.path || '';
  const isExternal = path.startsWith('http://') || path.startsWith('https://');

  if (isExternal && !options?.forceProxy) {
    return path;
  }

  const params = new URLSearchParams();
  if (options?.watermark) {
    params.set('watermark', 'true');
  }
  const query = params.toString();

  return `/api/photos/${photo.id}/image${query ? `?${query}` : ''}`;
};

export function PhotoGrid({
  photos,
  selectionMode = false,
  selectedPhotoIds = [],
  onToggleSelect,
  refreshFavoritesKey = 0,
}: PhotoGridProps) {
  const router = useRouter();
  const { data: session, update } = useSession();
  const isLoggedIn = Boolean(session);
  const hasWriteAccess = session?.user?.hasWriteAccess === true;
  
  // Normalize photos: ensure faces is always available (handle Face vs faces)
  const normalizePhoto = (photo: PhotoWithPeople): PhotoWithPeople => {
    const normalized = { ...photo };
    // If photo has Face (capital F) but no faces (lowercase), convert it
    if (!normalized.faces && (normalized as any).Face) {
      normalized.faces = (normalized as any).Face.map((face: any) => ({
        id: face.id,
        personId: face.person_id || face.personId,
        location: face.location,
        person: face.Person ? {
          id: face.Person.id,
          firstName: face.Person.first_name,
          lastName: face.Person.last_name,
          middleName: face.Person.middle_name,
          maidenName: face.Person.maiden_name,
          dateOfBirth: face.Person.date_of_birth,
        } : null,
      }));
    }
    return normalized;
  };
  
  // Normalize all photos
  const normalizedPhotos = useMemo(() => {
    return photos.map(normalizePhoto);
  }, [photos]);
  const [hoveredFace, setHoveredFace] = useState<{
    photoId: number;
    faceId: number;
    personId: number | null;
    personName: string | null;
  } | null>(null);
  const [reportingPhotoId, setReportingPhotoId] = useState<number | null>(null);
  const [reportedPhotos, setReportedPhotos] = useState<Map<number, { status: string }>>(new Map());
  const [favoritingPhotoId, setFavoritingPhotoId] = useState<number | null>(null);
  const [favoritedPhotos, setFavoritedPhotos] = useState<Map<number, boolean>>(new Map());
  const [showSignInRequiredDialog, setShowSignInRequiredDialog] = useState(false);
  const [loginDialogOpen, setLoginDialogOpen] = useState(false);
  const [registerDialogOpen, setRegisterDialogOpen] = useState(false);
  const [showRegisteredMessage, setShowRegisteredMessage] = useState(false);
  const [reportDialogPhotoId, setReportDialogPhotoId] = useState<number | null>(null);
  const [reportDialogComment, setReportDialogComment] = useState('');
  const [reportDialogError, setReportDialogError] = useState<string | null>(null);
  const imageRefs = useRef<Map<number, { naturalWidth: number; naturalHeight: number }>>(new Map());

  const handleMouseMove = useCallback((
    e: React.MouseEvent<HTMLDivElement | HTMLButtonElement>,
    photo: PhotoWithPeople
  ) => {
    // Skip face detection for videos
    if (isVideo(photo)) {
      setHoveredFace(null);
      return;
    }

    if (!photo.faces || photo.faces.length === 0) {
      setHoveredFace(null);
      return;
    }

    const container = e.currentTarget;
    const rect = container.getBoundingClientRect();
    const mouseX = e.clientX - rect.left;
    const mouseY = e.clientY - rect.top;

    // Get image dimensions from cache
    const imageData = imageRefs.current.get(photo.id);
    if (!imageData) {
      setHoveredFace(null);
      return;
    }

    const { naturalWidth, naturalHeight } = imageData;
    const containerWidth = rect.width;
    const containerHeight = rect.height;

    // Check each face to see if mouse is over it
    for (const face of photo.faces) {
      const location = parseFaceLocation(face.location);
      if (!location) continue;

      if (
        isPointInFace(
          mouseX,
          mouseY,
          location,
          naturalWidth,
          naturalHeight,
          containerWidth,
          containerHeight
        )
      ) {
        // Face detected!
        const person = face.person as any; // Handle both camelCase and snake_case
        const personName = person
          ? `${person.firstName || person.first_name || ''} ${person.lastName || person.last_name || ''}`.trim()
          : null;
        
        setHoveredFace({
          photoId: photo.id,
          faceId: face.id,
          personId: face.personId,
          personName: personName || null,
        });
        return;
      }
    }

    // No face detected
    setHoveredFace(null);
  }, []);

  const handleImageLoad = useCallback((photoId: number, img: HTMLImageElement) => {
    imageRefs.current.set(photoId, {
      naturalWidth: img.naturalWidth,
      naturalHeight: img.naturalHeight,
    });
  }, []);

  const handleDownloadPhoto = useCallback((event: React.MouseEvent, photo: Photo) => {
    event.stopPropagation();
    const link = document.createElement('a');
    link.href = getPhotoDownloadUrl(photo, { watermark: !isLoggedIn });
    link.download = getPhotoFilename(photo);
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  }, [isLoggedIn]);

  // Remove duplicates by ID to prevent React key errors
  // Memoized to prevent recalculation on every render
  // Must be called before any early returns to maintain hooks order
  const uniquePhotos = useMemo(() => {
    return normalizedPhotos.filter((photo, index, self) => 
      index === self.findIndex((p) => p.id === photo.id)
    );
  }, [normalizedPhotos]);

  // Fetch report status for all photos when component mounts or photos change
  // Uses batch API to reduce N+1 query problem
  // Must be called before any early returns to maintain hooks order
  useEffect(() => {
    if (!session?.user?.id) {
      setReportedPhotos(new Map());
      return;
    }

    const fetchReportStatuses = async () => {
      const photoIds = uniquePhotos.map(p => p.id);

      if (photoIds.length === 0) {
        return;
      }

      try {
        // Batch API call - single request for all photos
        const response = await fetch('/api/photos/reports/batch', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({ photoIds }),
        });

        if (!response.ok) {
          throw new Error('Failed to fetch report statuses');
        }

        const data = await response.json();
      const statusMap = new Map<number, { status: string }>();
      
        // Process batch results
        if (data.results) {
          for (const [photoIdStr, result] of Object.entries(data.results)) {
            const photoId = parseInt(photoIdStr, 10);
            const reportData = result as { reported: boolean; status?: string };
            if (reportData.reported && reportData.status) {
              statusMap.set(photoId, { status: reportData.status });
        }
          }
        }

      setReportedPhotos(statusMap);
      } catch (error) {
        console.error('Error fetching batch report statuses:', error);
        // Fallback: set empty map on error
        setReportedPhotos(new Map());
      }
    };

    fetchReportStatuses();
  }, [uniquePhotos, session?.user?.id]);

  // Fetch favorite status for all photos when component mounts or photos change
  // Uses batch API to reduce N+1 query problem
  useEffect(() => {
    if (!session?.user?.id) {
      setFavoritedPhotos(new Map());
      return;
    }

    const fetchFavoriteStatuses = async () => {
      const photoIds = uniquePhotos.map(p => p.id);

      if (photoIds.length === 0) {
        return;
      }

      try {
        // Batch API call - single request for all photos
        const response = await fetch('/api/photos/favorites/batch', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({ photoIds }),
        });

        if (!response.ok) {
          throw new Error('Failed to fetch favorite statuses');
        }

        const data = await response.json();
        const favoriteMap = new Map<number, boolean>();
        
        // Process batch results
        if (data.results) {
          for (const [photoIdStr, isFavorited] of Object.entries(data.results)) {
            const photoId = parseInt(photoIdStr, 10);
            favoriteMap.set(photoId, isFavorited as boolean);
          }
        }

        setFavoritedPhotos(favoriteMap);
      } catch (error) {
        console.error('Error fetching batch favorite statuses:', error);
        // Fallback: set empty map on error
        setFavoritedPhotos(new Map());
      }
    };

    fetchFavoriteStatuses();
  }, [uniquePhotos, session?.user?.id, refreshFavoritesKey]);

  // Filter out videos for slideshow navigation (only images)
  // Note: This is only used for slideshow context, not for navigation
  // Memoized to maintain consistent hook order
  const imageOnlyPhotos = useMemo(() => {
    return uniquePhotos.filter((p) => !isVideo(p));
  }, [uniquePhotos]);

  const handlePhotoClick = (photoId: number, index: number) => {
    const photo = uniquePhotos.find((p) => p.id === photoId);
    if (!photo) return;

    // Use the full photos list (including videos) for navigation
    // This ensures consistent navigation whether clicking a photo or video
    const allPhotoIds = uniquePhotos.map((p) => p.id).join(',');
    const photoIndex = uniquePhotos.findIndex((p) => p.id === photoId);
    
    if (photoIndex === -1) return;

    // Update URL with photo query param while preserving existing params (filters, etc.)
    const params = new URLSearchParams(window.location.search);
    params.set('photo', photoId.toString());
    params.set('photos', allPhotoIds);
    params.set('index', photoIndex.toString());
    router.push(`/?${params.toString()}`, { scroll: false });
  };

  const handlePhotoInteraction = (photoId: number, index: number) => {
    if (selectionMode && onToggleSelect) {
      onToggleSelect(photoId);
      return;
    }

    handlePhotoClick(photoId, index);
  };

  const resetReportDialog = () => {
    setReportDialogPhotoId(null);
    setReportDialogComment('');
    setReportDialogError(null);
  };

  const handleUndoReport = async (photoId: number) => {
    const reportInfo = reportedPhotos.get(photoId);
    const isReported = reportInfo && reportInfo.status === 'pending';

    if (!isReported || reportingPhotoId === photoId) {
      return;
    }

    setReportingPhotoId(photoId);

    try {
      const response = await fetch(`/api/photos/${photoId}/report`, {
        method: 'DELETE',
        headers: {
          'Content-Type': 'application/json',
        },
      });

      if (!response.ok) {
        const error = await response.json();
        if (response.status === 401) {
          alert('Please sign in to report photos');
        } else if (response.status === 403) {
          alert('Cannot undo report that has already been reviewed');
        } else if (response.status === 404) {
          alert('Report not found');
        } else {
          alert(error.error || 'Failed to undo report');
        }
        return;
      }

      const newMap = new Map(reportedPhotos);
      newMap.delete(photoId);
      setReportedPhotos(newMap);
      alert('Report undone successfully.');
    } catch (error) {
      console.error('Error undoing photo report:', error);
      alert('Failed to undo report. Please try again.');
    } finally {
      setReportingPhotoId(null);
    }
  };

  const handleReportButtonClick = async (e: React.MouseEvent, photoId: number) => {
    e.stopPropagation(); // Prevent photo click from firing

    if (!session) {
      setShowSignInRequiredDialog(true);
      return;
    }

    if (reportingPhotoId === photoId) return; // Already processing

    const reportInfo = reportedPhotos.get(photoId);
    const isPending = reportInfo && reportInfo.status === 'pending';
    const isDismissed = reportInfo && reportInfo.status === 'dismissed';

    if (isDismissed) {
      alert('This report was dismissed by an administrator and cannot be resubmitted.');
      return;
    }

    if (isPending) {
      await handleUndoReport(photoId);
      return;
    }

    setReportDialogPhotoId(photoId);
    setReportDialogComment('');
    setReportDialogError(null);
  };

  const handleSubmitReport = async () => {
    if (reportDialogPhotoId === null) {
      return;
    }

    const trimmedComment = reportDialogComment.trim();
    if (trimmedComment.length > REPORT_COMMENT_MAX_LENGTH) {
      setReportDialogError(`Comment must be ${REPORT_COMMENT_MAX_LENGTH} characters or less.`);
      return;
    }

    setReportDialogError(null);
    setReportingPhotoId(reportDialogPhotoId);

    try {
      const response = await fetch(`/api/photos/${reportDialogPhotoId}/report`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({
          comment: trimmedComment.length > 0 ? trimmedComment : null,
        }),
      });

      if (!response.ok) {
        const error = await response.json().catch(() => null);
        if (response.status === 401) {
          setShowSignInRequiredDialog(true);
        } else if (response.status === 403) {
          alert(error?.error || 'Cannot re-report this photo.');
        } else if (response.status === 409) {
          alert('You have already reported this photo');
        } else if (response.status === 400) {
          setReportDialogError(error?.error || 'Invalid comment');
          return;
        } else {
          alert(error?.error || 'Failed to report photo. Please try again.');
        }
        return;
      }

      const newMap = new Map(reportedPhotos);
      newMap.set(reportDialogPhotoId, { status: 'pending' });
      setReportedPhotos(newMap);

      const previousReport = reportedPhotos.get(reportDialogPhotoId);
      alert(
        previousReport && previousReport.status === 'reviewed'
          ? 'Photo re-reported successfully. Thank you for your report.'
          : 'Photo reported successfully. Thank you for your report.'
      );
      resetReportDialog();
    } catch (error) {
      console.error('Error reporting photo:', error);
      alert('Failed to create report. Please try again.');
    } finally {
      setReportingPhotoId(null);
    }
  };

  const handleToggleFavorite = async (e: React.MouseEvent, photoId: number) => {
    e.stopPropagation(); // Prevent photo click from firing

    if (!session) {
      setShowSignInRequiredDialog(true);
      return;
    }

    if (favoritingPhotoId === photoId) return; // Already processing

    setFavoritingPhotoId(photoId);

    try {
      const response = await fetch(`/api/photos/${photoId}/favorite`, {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
      });

      if (!response.ok) {
        const error = await response.json();
        if (response.status === 401) {
          setShowSignInRequiredDialog(true);
        } else {
          alert(error.error || 'Failed to toggle favorite');
        }
        return;
      }

      const data = await response.json();
      const newMap = new Map(favoritedPhotos);
      newMap.set(photoId, data.favorited);
      setFavoritedPhotos(newMap);
    } catch (error) {
      console.error('Error toggling favorite:', error);
      alert('Failed to toggle favorite. Please try again.');
    } finally {
      setFavoritingPhotoId(null);
    }
  };

  return (
    <TooltipProvider delayDuration={200}>
      <div className="grid grid-cols-2 gap-4 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5">
        {uniquePhotos.map((photo, index) => {
          const hoveredFaceForPhoto = hoveredFace?.photoId === photo.id ? hoveredFace : null;
          const isSelected = selectionMode && selectedPhotoIds.includes(photo.id);
          
          // Determine tooltip text while respecting auth visibility rules
          let tooltipText: string = photo.filename; // Default fallback
          const isVideoPhoto = isVideo(photo);
          
          if (isVideoPhoto) {
            tooltipText = `Video: ${photo.filename}`;
          } else if (hoveredFaceForPhoto) {
            // Hovering over a specific face
            if (hoveredFaceForPhoto.personName) {
              // Face is identified - show person name (only if logged in)
              tooltipText = isLoggedIn ? hoveredFaceForPhoto.personName : photo.filename;
            } else {
              // Face is not identified - show "Identify" if user has write access or is not logged in
              tooltipText = (!session || hasWriteAccess) ? 'Identify' : photo.filename;
            }
          } else if (isLoggedIn) {
            // Hovering over photo (not a face) - show "People: " + names
            const peopleNames = getPeopleNames(photo);
            tooltipText = peopleNames.length > 0
              ? `People: ${peopleNames.join(', ')}`
              : photo.filename;
          }
          
          return (
            <TooltipPrimitive.Root key={photo.id} delayDuration={200}>
              <div className="group relative aspect-square">
                <TooltipTrigger asChild>
                  <button
                    type="button"
                    onClick={() => handlePhotoInteraction(photo.id, index)}
                    aria-pressed={isSelected}
                    className={`relative w-full h-full overflow-hidden rounded-lg bg-gray-100 cursor-pointer outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-900 ${isSelected ? 'ring-2 ring-blue-500 ring-offset-2' : ''}`}
                    onMouseMove={(e) => !isVideoPhoto && handleMouseMove(e, photo)}
                    onMouseLeave={() => setHoveredFace(null)}
                  >
                    <Image
                      src={getImageSrc(photo, { watermark: !isLoggedIn, thumbnail: isVideoPhoto })}
                      alt={photo.filename}
                      fill
                      className="object-contain bg-black/5 transition-transform duration-300 group-hover:scale-105"
                      sizes="(max-width: 640px) 50vw, (max-width: 1024px) 33vw, 20vw"
                      priority={index < 9}
                      onLoad={(e) => !isVideoPhoto && handleImageLoad(photo.id, e.currentTarget)}
                    />
                    <div className="absolute inset-0 bg-black/0 transition-colors group-hover:bg-black/10" />
                    {/* Video play icon overlay */}
                    {isVideoPhoto && (
                      <div className="absolute inset-0 flex items-center justify-center bg-black/20 group-hover:bg-black/30 transition-colors">
                        <div className="rounded-full bg-white/90 p-3 shadow-lg group-hover:bg-white transition-colors">
                          <Play className="h-6 w-6 text-secondary fill-secondary ml-1" />
                        </div>
                      </div>
                    )}
                    {selectionMode && (
                      <>
                        <div
                          className={`absolute inset-0 rounded-lg border-2 transition-colors pointer-events-none ${isSelected ? 'border-orange-600' : 'border-transparent'}`}
                        />
                        <div
                          className={`absolute right-2 top-2 z-10 rounded-full border border-white/50 p-1 text-white transition-colors ${isSelected ? 'bg-orange-600' : 'bg-black/60'}`}
                        >
                          <Check className="h-4 w-4" />
                        </div>
                      </>
                    )}
                  </button>
                </TooltipTrigger>
                
                {/* Download Button - Top Left Corner */}
                <button
                  type="button"
                  onClick={(e) => handleDownloadPhoto(e, photo)}
                  className="absolute left-2 top-2 z-10 p-1.5 rounded-full text-white opacity-0 group-hover:opacity-100 transition-opacity bg-black/50 hover:bg-black/70"
                  aria-label="Download photo"
                  title="Download photo"
                >
                  <Download className="h-4 w-4" />
                </button>
                
                {/* Report Button - Left Bottom Corner - Show always */}
                {(() => {
                  if (!session) {
                    // Not logged in - show basic report button
                    return (
                      <button
                        type="button"
                        onClick={(e) => handleReportButtonClick(e, photo.id)}
                        className="absolute left-2 bottom-2 z-10 p-1.5 rounded-full text-white opacity-0 group-hover:opacity-100 transition-opacity bg-black/50 hover:bg-black/70"
                        aria-label="Report inappropriate photo"
                        title="Report inappropriate photo"
                      >
                        <Flag className="h-4 w-4" />
                      </button>
                    );
                  }

                  // Logged in - show button with status
                  const reportInfo = reportedPhotos.get(photo.id);
                  const isReported = reportInfo && reportInfo.status === 'pending';
                  const isReviewed = reportInfo && reportInfo.status === 'reviewed';
                  const isDismissed = reportInfo && reportInfo.status === 'dismissed';
                  
                  let tooltipText: string;
                  let buttonClass: string;
                  
                  if (isReported) {
                    tooltipText = 'Reported as inappropriate. Click to undo';
                    buttonClass = 'bg-red-600/70 hover:bg-red-600/90';
                  } else if (isReviewed) {
                    tooltipText = 'Report reviewed and kept. Click to report again';
                    buttonClass = 'bg-green-600/70 hover:bg-green-600/90';
                  } else if (isDismissed) {
                    tooltipText = 'Report dismissed';
                    buttonClass = 'bg-gray-600/70 hover:bg-gray-600/90';
                  } else {
                    tooltipText = 'Report inappropriate photo';
                    buttonClass = 'bg-black/50 hover:bg-black/70';
                  }
                  
                  return (
                    <button
                      type="button"
                      onClick={(e) => handleReportButtonClick(e, photo.id)}
                      disabled={reportingPhotoId === photo.id || isDismissed}
                      className={`absolute left-2 bottom-2 z-10 p-1.5 rounded-full text-white opacity-0 group-hover:opacity-100 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed ${buttonClass}`}
                      aria-label={tooltipText}
                      title={tooltipText}
                    >
                      <Flag className={`h-4 w-4 ${isReported || isReviewed ? 'fill-current' : ''}`} />
                    </button>
                  );
                })()}

                {/* Favorite Button - Right Bottom Corner - Show always */}
                {(() => {
                  if (!session) {
                    // Not logged in - show basic favorite button
                    return (
                      <button
                        type="button"
                        onClick={(e) => handleToggleFavorite(e, photo.id)}
                        className="absolute right-2 bottom-2 z-10 p-1.5 rounded-full text-white opacity-0 group-hover:opacity-100 transition-opacity bg-black/50 hover:bg-black/70"
                        aria-label="Add to favorites"
                        title="Add to favorites (sign in required)"
                      >
                        <Heart className="h-4 w-4" />
                      </button>
                    );
                  }

                  // Logged in - show button with favorite status
                  const isFavorited = favoritedPhotos.get(photo.id) || false;
                  
                  return (
                    <button
                      type="button"
                      onClick={(e) => handleToggleFavorite(e, photo.id)}
                      disabled={favoritingPhotoId === photo.id}
                      className={`absolute right-2 bottom-2 z-10 p-1.5 rounded-full text-white opacity-0 group-hover:opacity-100 transition-opacity disabled:opacity-50 disabled:cursor-not-allowed ${
                        isFavorited 
                          ? 'bg-red-600/70 hover:bg-red-600/90' 
                          : 'bg-black/50 hover:bg-black/70'
                      }`}
                      aria-label={isFavorited ? 'Remove from favorites' : 'Add to favorites'}
                      title={isFavorited ? 'Remove from favorites' : 'Add to favorites'}
                    >
                      <Heart className={`h-4 w-4 ${isFavorited ? 'fill-current' : ''}`} />
                    </button>
                  );
                })()}
              </div>
              <TooltipContent 
                side="bottom" 
                sideOffset={5}
                className="max-w-xs bg-blue-400 text-white z-[9999]"
                arrowColor="blue-400"
              >
                <p className="text-sm font-medium">{tooltipText || photo.filename}</p>
              </TooltipContent>
            </TooltipPrimitive.Root>
          );
        })}
      </div>

      {/* Report Comment Dialog */}
      <Dialog
        open={reportDialogPhotoId !== null}
        onOpenChange={(open) => {
          if (!open) {
            resetReportDialog();
          }
        }}
      >
        <DialogContent className="sm:max-w-[500px]">
          <DialogHeader>
            <DialogTitle>Report Photo</DialogTitle>
            <DialogDescription>
              Optionally include a short comment to help administrators understand the issue.
            </DialogDescription>
          </DialogHeader>
          <div className="py-4">
            <label htmlFor="report-comment" className="text-sm font-medium text-secondary">
              Comment (optional)
            </label>
            <textarea
              id="report-comment"
              value={reportDialogComment}
              onChange={(event) => setReportDialogComment(event.target.value)}
              maxLength={REPORT_COMMENT_MAX_LENGTH}
              className="mt-2 w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-900"
              rows={4}
              placeholder="Add a short note about why this photo should be reviewed..."
            />
            <div className="mt-1 flex justify-between text-xs text-gray-500">
              <span>{`${reportDialogComment.length}/${REPORT_COMMENT_MAX_LENGTH} characters`}</span>
              {reportDialogError && <span className="text-red-600">{reportDialogError}</span>}
            </div>
          </div>
          <DialogFooter className="gap-2 sm:gap-0">
            <Button
              variant="outline"
              onClick={() => {
                resetReportDialog();
              }}
            >
              Cancel
            </Button>
            <Button
              onClick={handleSubmitReport}
              disabled={
                reportDialogPhotoId === null || reportingPhotoId === reportDialogPhotoId
              }
            >
              {reportDialogPhotoId !== null && reportingPhotoId === reportDialogPhotoId
                ? 'Reporting...'
                : 'Report photo'}
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Sign In Required Dialog for Report */}
      <Dialog open={showSignInRequiredDialog} onOpenChange={setShowSignInRequiredDialog}>
        <DialogContent className="sm:max-w-[500px]">
          <DialogHeader>
            <DialogTitle>Sign In Required</DialogTitle>
            <DialogDescription>
              You need to be signed in to report photos. Your reports will be reviewed by administrators.
            </DialogDescription>
          </DialogHeader>
          <div className="py-4">
            <p className="text-sm text-gray-600 mb-4">
              Please sign in or create an account to continue.
            </p>
            <div className="flex gap-2">
              <Button
                onClick={() => {
                  setLoginDialogOpen(true);
                }}
                className="flex-1"
              >
                Sign in
              </Button>
              <Button
                variant="outline"
                onClick={() => {
                  setRegisterDialogOpen(true);
                }}
                className="flex-1"
              >
                Register
              </Button>
            </div>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setShowSignInRequiredDialog(false)}>
              Cancel
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      {/* Login Dialog */}
      <LoginDialog
        open={loginDialogOpen}
        onOpenChange={(open) => {
          setLoginDialogOpen(open);
          if (!open) {
            setShowRegisteredMessage(false);
          }
        }}
        onSuccess={async () => {
          await update();
          router.refresh();
          setShowSignInRequiredDialog(false);
        }}
        onOpenRegister={() => {
          setLoginDialogOpen(false);
          setRegisterDialogOpen(true);
        }}
        registered={showRegisteredMessage}
        callbackUrl={typeof window !== 'undefined' ? window.location.pathname + window.location.search : '/'}
      />

      {/* Register Dialog */}
      <RegisterDialog
        open={registerDialogOpen}
        onOpenChange={(open) => {
          setRegisterDialogOpen(open);
          if (!open) {
            setShowRegisteredMessage(false);
          }
        }}
        onSuccess={async () => {
          await update();
          router.refresh();
          setShowSignInRequiredDialog(false);
        }}
        onOpenLogin={() => {
          setShowRegisteredMessage(true);
          setRegisterDialogOpen(false);
          setLoginDialogOpen(true);
        }}
        callbackUrl={typeof window !== 'undefined' ? window.location.pathname + window.location.search : '/'}
      />
    </TooltipProvider>
  );
}



