import React, { useEffect, useMemo, useState, useRef } from "react";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Button } from "@/components/ui/button";
import { Delete, Edit, Eye, FileCheck, Scan, Upload, X, FileText, Download, Trash2, Camera, RefreshCw } from "lucide-react";
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination";
import { apiRequest, queryClient } from "@/lib/queryClient";
import { useMutation, useQuery } from "@tanstack/react-query";
import LoadingScreen from "@/components/ui/LoadingScreen";
import { useToast } from "@/hooks/use-toast";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import { AddPatientModal } from "./add-patient-modal";
import { DeleteConfirmationDialog } from "@/components/ui/deleteDialog";
import { useAuth } from "@/hooks/use-auth";
import { PatientSearch, SearchCriteria } from "./patient-search";
import { useDebounce } from "use-debounce";
import { cn } from "@/lib/utils";
import { Checkbox } from "@/components/ui/checkbox";
import { formatDateToHumanReadable } from "@/utils/dateUtils";
import { Patient, UpdatePatient } from "@repo/db/types";
import { PatientFinancialsModal } from "./patient-financial-modal";
import { getPageNumbers } from "@/utils/pageNumberGenerator";
import {
  uploadDocument,
  getPatientDocuments,
  deleteDocument,
  viewDocument,
  downloadDocument,
  scanDocument,
  formatFileSize,
  type PatientDocument
} from "@/lib/api/documents";

interface PatientApiResponse {
  patients: Patient[];
  totalCount: number;
}

interface PatientTableProps {
  allowEdit?: boolean;
  allowView?: boolean;
  allowDelete?: boolean;
  allowCheckbox?: boolean;
  allowNewClaim?: boolean;
  allowFinancial?: boolean;
  onNewClaim?: (patientId: number) => void;
  onSelectPatient?: (patient: Patient | null) => void;
  onPageChange?: (page: number) => void;
  onSearchChange?: (searchTerm: string) => void;
}

// 🔑 exported base key
export const QK_PATIENTS_BASE = ["patients"] as const;
// helper (optional) – mirrors your current key structure
export const qkPatients = (page: number, search: string) =>
  [...QK_PATIENTS_BASE, { page, search }] as const;

export function PatientTable({
  allowEdit,
  allowView,
  allowDelete,
  allowCheckbox,
  allowNewClaim,
  allowFinancial,
  onNewClaim,
  onSelectPatient,
  onPageChange,
  onSearchChange,
}: PatientTableProps) {
  const { toast } = useToast();
  const { user } = useAuth();
  const isAdmin = user?.username === "admin";

  const [currentPatient, setCurrentPatient] = useState<Patient | undefined>(
    undefined
  );

  const [isAddPatientOpen, setIsAddPatientOpen] = useState(false);
  const [isViewPatientOpen, setIsViewPatientOpen] = useState(false);
  const [isDeletePatientOpen, setIsDeletePatientOpen] = useState(false);
  const [isFinancialsOpen, setIsFinancialsOpen] = useState(false);
  const [modalPatientId, setModalPatientId] = useState<number | null>(null);

  const [currentPage, setCurrentPage] = useState(1);
  const patientsPerPage = 5;
  const offset = (currentPage - 1) * patientsPerPage;

  const [isSearchActive, setIsSearchActive] = useState(false);
  const [searchCriteria, setSearchCriteria] = useState<SearchCriteria | null>(
    null
  );
  const [debouncedSearchCriteria] = useDebounce(searchCriteria, 500);

  const [selectedPatientId, setSelectedPatientId] = useState<number | null>(
    null
  );
  const [expandedPatientId, setExpandedPatientId] = useState<number | null>(null);

  // Real document data state
  const [patientDocuments, setPatientDocuments] = useState<{ [key: number]: PatientDocument[] }>({});
  const [documentsLoading, setDocumentsLoading] = useState<{ [key: number]: boolean }>({});

  // Document viewer modal state
  const [documentViewerOpen, setDocumentViewerOpen] = useState(false);
  const [viewingDocument, setViewingDocument] = useState<{ url: string; name: string } | null>(null);

  // Thumbnail cache for image documents
  const [documentThumbnails, setDocumentThumbnails] = useState<{ [key: number]: string | null }>({});

  // Camera modal state
  const [cameraOpen, setCameraOpen] = useState(false);
  const [selectedPatientIdForCamera, setSelectedPatientIdForCamera] = useState<number | null>(null);
  const [stream, setStream] = useState<MediaStream | null>(null);
  const [capturedImage, setCapturedImage] = useState<string | null>(null);
  const [cameraPermission, setCameraPermission] = useState<'granted' | 'denied' | 'prompt' | 'unknown'>('unknown');
  const [isRequestingPermission, setIsRequestingPermission] = useState(false);
  const videoRef = useRef<HTMLVideoElement>(null);
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const [facingMode, setFacingMode] = useState<'user' | 'environment'>('environment');

  // Cleanup blob URL when modal closes
  const handleDocumentViewerClose = () => {
    if (viewingDocument && viewingDocument.url.startsWith('blob:')) {
      URL.revokeObjectURL(viewingDocument.url);
    }
    setDocumentViewerOpen(false);
    setViewingDocument(null);
  };

  // Get thumbnail URL for image documents
  const getDocumentThumbnail = async (doc: PatientDocument): Promise<string | null> => {
    if (!doc.mimeType.startsWith('image/')) {
      return null;
    }

    try {
      // Use the full URL from the database directly
      const documentUrl = doc.filePath;
      // Static files don't need authentication headers
      const response = await fetch(documentUrl);

      if (!response.ok) {
        return null;
      }

      const blob = await response.blob();
      return URL.createObjectURL(blob);
    } catch (error) {
      console.error('Error loading thumbnail:', error);
      return null;
    }
  };

  // Load thumbnails for image documents
  const loadDocumentThumbnails = async (documents: PatientDocument[]) => {
    const imageDocs = documents.filter(doc => doc.mimeType.startsWith('image/'));

    for (const doc of imageDocs) {
      if (!documentThumbnails[doc.id]) {
        const thumbnailUrl = await getDocumentThumbnail(doc);
        setDocumentThumbnails(prev => ({
          ...prev,
          [doc.id]: thumbnailUrl
        }));
      }
    }
  };

  // Check camera permissions
  const checkCameraPermission = async () => {
    try {
      console.log('Checking camera permission...');
      const permission = await navigator.permissions.query({ name: 'camera' as PermissionName });
      console.log('Permission state:', permission.state);
      setCameraPermission(permission.state as 'granted' | 'denied' | 'prompt');

      // Listen for permission changes
      permission.addEventListener('change', () => {
        console.log('Permission changed to:', permission.state);
        setCameraPermission(permission.state as 'granted' | 'denied' | 'prompt');
      });

      return permission.state;
    } catch (error) {
      console.log('Permission API not supported, will try getUserMedia directly');
      return 'unknown';
    }
  };

  // Check if running on localhost vs remote IP
  const isLocalhost = () => {
    return window.location.hostname === 'localhost' ||
      window.location.hostname === '127.0.0.1' ||
      window.location.hostname.includes('localhost');
  };

  // Check if any camera devices are available
  const checkCameraDevices = async () => {
    try {
      const devices = await navigator.mediaDevices.enumerateDevices();
      const videoDevices = devices.filter(device => device.kind === 'videoinput');
      console.log('Available camera devices:', videoDevices.length);
      console.log('Current hostname:', window.location.hostname);
      console.log('Is localhost:', isLocalhost());
      return videoDevices.length > 0;
    } catch (error) {
      console.error('Error checking camera devices:', error);
      return false;
    }
  };

  // Request camera permission
  const requestCameraPermission = async () => {
    setIsRequestingPermission(true);

    // Check if running on secure context
    if (!isLocalhost() && window.location.protocol !== 'https:') {
      toast({
        title: "HTTPS Required",
        description: "Camera access requires HTTPS when accessing from remote devices. Please use https:// or access from localhost.",
        variant: "destructive",
      });
      setIsRequestingPermission(false);
      return false;
    }

    // First check if any camera devices are available
    const hasCamera = await checkCameraDevices();
    if (!hasCamera) {
      toast({
        title: "No Camera Found",
        description: "No camera device was detected. Please ensure you have a camera connected and try again.",
        variant: "destructive",
      });
      setIsRequestingPermission(false);
      return false;
    }

    try {
      console.log('Requesting camera permission...');
      const mediaStream = await navigator.mediaDevices.getUserMedia({
        video: {
          facingMode: 'environment',
          width: { ideal: 1920 },
          height: { ideal: 1080 }
        }
      });

      console.log('Camera permission granted!');
      // Permission granted
      setCameraPermission('granted');
      setStream(mediaStream);
      if (videoRef.current) {
        videoRef.current.srcObject = mediaStream;
      }

      // Stop the stream for now, will be started when needed
      mediaStream.getTracks().forEach(track => track.stop());
      setStream(null);

      toast({
        title: "Camera Permission Granted",
        description: "You can now use the camera to scan documents",
      });

      return true;
    } catch (error: any) {
      console.error('Camera permission error:', error);

      // Handle different types of camera errors
      if (error.name === 'NotFoundError' || error.message.includes('Requested device not found')) {
        setCameraPermission('denied');
        toast({
          title: "No Camera Found",
          description: "No camera device was detected. Please ensure you have a camera connected and try again.",
          variant: "destructive",
        });
      } else if (error.name === 'NotAllowedError' || error.message.includes('Permission denied')) {
        setCameraPermission('denied');
        toast({
          title: "Camera Permission Denied",
          description: "Please allow camera access in your browser settings to scan documents",
          variant: "destructive",
        });
      } else if (error.name === 'NotReadableError' || error.message.includes('Already in use')) {
        setCameraPermission('denied');
        toast({
          title: "Camera Already in Use",
          description: "The camera is being used by another application. Please close other apps using the camera and try again.",
          variant: "destructive",
        });
      } else if (error.name === 'NotSupportedError' || error.message.includes('secure context')) {
        setCameraPermission('denied');
        toast({
          title: "HTTPS Required",
          description: "Camera access requires HTTPS. Please use https:// or access from localhost for development.",
          variant: "destructive",
        });
      } else {
        setCameraPermission('denied');
        toast({
          title: "Camera Error",
          description: "Unable to access camera. Please check your camera settings and try again.",
          variant: "destructive",
        });
      }

      return false;
    } finally {
      setIsRequestingPermission(false);
    }
  };

  // Camera functions
  const startCamera = async () => {
    try {
      const mediaStream = await navigator.mediaDevices.getUserMedia({
        video: {
          facingMode: facingMode,
          width: { ideal: 1920 },
          height: { ideal: 1080 }
        }
      });
      setStream(mediaStream);
      if (videoRef.current) {
        videoRef.current.srcObject = mediaStream;
      }
    } catch (error) {
      console.error('Error accessing camera:', error);
      toast({
        title: "Camera Error",
        description: "Unable to access camera. Please check permissions.",
        variant: "destructive",
      });
    }
  };

  const stopCamera = () => {
    if (stream) {
      stream.getTracks().forEach(track => track.stop());
      setStream(null);
    }
  };

  const capturePhoto = () => {
    if (videoRef.current && canvasRef.current) {
      const video = videoRef.current;
      const canvas = canvasRef.current;
      const context = canvas.getContext('2d');

      if (context) {
        canvas.width = video.videoWidth;
        canvas.height = video.videoHeight;
        context.drawImage(video, 0, 0, canvas.width, canvas.height);
        const imageData = canvas.toDataURL('image/jpeg', 0.8);
        setCapturedImage(imageData);
        stopCamera();
      }
    }
  };

  const retakePhoto = () => {
    setCapturedImage(null);
    startCamera();
  };

  const toggleFacingMode = () => {
    setFacingMode(prev => prev === 'user' ? 'environment' : 'user');
    if (stream) {
      stopCamera();
    }
  };

  // Restart camera when facingMode changes
  useEffect(() => {
    if (cameraOpen && !capturedImage) {
      startCamera();
    }
  }, [facingMode]);

  const handleFinancialsModalChange = (v: boolean) => {
    setIsFinancialsOpen(v);
    if (!v) setModalPatientId(null);
  };

  const handleScanDocument = async (patientId: number) => {
    console.log('handleScanDocument called with patientId:', patientId);
    if (!patientId) {
      console.error('No patient ID provided');
      toast({
        title: "Error",
        description: "Please select a patient first",
        variant: "destructive",
      });
      return;
    }

    setSelectedPatientIdForCamera(patientId);
    setCapturedImage(null);
    setFacingMode('environment'); // Reset to back camera by default

    // Directly request permission which triggers browser prompt
    const granted = await requestCameraPermission();
    if (granted) {
      setCameraOpen(true);
    }
  };

  const handleCameraClose = () => {
    stopCamera();
    setCameraOpen(false);
    setSelectedPatientIdForCamera(null);
    setCapturedImage(null);
  };

  const saveCapturedPhoto = async () => {
    if (!capturedImage || !selectedPatientIdForCamera) return;

    try {
      // Convert data URL to blob
      const response = await fetch(capturedImage);
      const blob = await response.blob();
      const file = new File([blob], `scan_${Date.now()}.jpg`, { type: 'image/jpeg' });

      // Upload using existing upload function
      await uploadDocument(selectedPatientIdForCamera, file);

      // Emit document upload event
      window.dispatchEvent(new CustomEvent('documentUploaded', { 
        detail: { patientId: selectedPatientIdForCamera, fileName: `scan_${Date.now()}.jpg` }
      }));

      // Also set storage event for cross-tab communication
      localStorage.setItem('documentUploaded', Date.now().toString());

      // Refresh documents for this patient
      await loadPatientDocuments(selectedPatientIdForCamera);

      toast({
        title: "Success",
        description: "Document scanned and uploaded successfully",
        variant: "default",
      });

      handleCameraClose();
    } catch (error) {
      console.error('Error saving scanned document:', error);
      toast({
        title: "Error",
        description: "Failed to save scanned document",
        variant: "destructive",
      });
    }
  };

  // Start camera when modal opens
  useEffect(() => {
    if (cameraOpen && !capturedImage) {
      startCamera();
    }

    return () => {
      if (stream) {
        stopCamera();
      }
    };
  }, [cameraOpen, capturedImage]);

  const handleSelectPatient = (patient: Patient) => {
    const isSelected = selectedPatientId === patient.id;
    const newSelectedId = isSelected ? null : patient.id;
    setSelectedPatientId(newSelectedId ? Number(newSelectedId) : null);

    if (onSelectPatient) {
      onSelectPatient(isSelected ? null : patient);
    }
  };

  const handleClearSelection = () => {
    setSelectedPatientId(null);
    if (onSelectPatient) {
      onSelectPatient(null);
    }
  };

  const handleUploadFiles = async () => {
    if (selectedPatientId) {
      const input = document.createElement('input');
      input.type = 'file';
      input.multiple = true;
      input.accept = '.pdf,.jpg,.jpeg,.png,.doc,.docx';
      input.onchange = async (e) => {
        const files = (e.target as HTMLInputElement).files;
        if (files && files.length > 0) {
          try {
            const uploadPromises = Array.from(files).map(file =>
              uploadDocument(selectedPatientId, file)
            );

            const results = await Promise.all(uploadPromises);

            // Emit document upload event
            window.dispatchEvent(new CustomEvent('documentUploaded', { 
              detail: { patientId: selectedPatientId, fileCount: files.length, files: Array.from(files).map(f => f.name) }
            }));

            // Also set storage event for cross-tab communication
            localStorage.setItem('documentUploaded', Date.now().toString());

            // Refresh documents for this patient
            await loadPatientDocuments(selectedPatientId);

            toast({
              title: "Files Uploaded",
              description: `${files.length} file(s) uploaded successfully to patient ID: ${selectedPatientId}`,
              variant: "default",
            });
          } catch (error) {
            console.error('Upload error:', error);
            toast({
              title: "Upload Failed",
              description: error instanceof Error ? error.message : "Failed to upload files",
              variant: "destructive",
            });
          }
        }
      };
      input.click();
    }
  };

  // Load documents for a patient
  const loadPatientDocuments = async (patientId: number) => {
    try {
      setDocumentsLoading(prev => ({ ...prev, [patientId]: true }));
      const response = await getPatientDocuments(patientId);
      setPatientDocuments(prev => ({ ...prev, [patientId]: response.documents }));

      // Load thumbnails for image documents
      await loadDocumentThumbnails(response.documents);
    } catch (error) {
      console.error('Error loading documents:', error);
      toast({
        title: "Error",
        description: "Failed to load documents",
        variant: "destructive",
      });
    } finally {
      setDocumentsLoading(prev => ({ ...prev, [patientId]: false }));
    }
  };

  const handleToggleDocuments = async (patientId: number) => {
    const isExpanding = expandedPatientId !== patientId;
    setExpandedPatientId(isExpanding ? patientId : null);

    // Load documents if expanding and not already loaded
    if (isExpanding && !patientDocuments[patientId]) {
      await loadPatientDocuments(patientId);
    }
  };

  const handleViewDocument = async (documentId: number, patientId: number) => {
    try {
      const doc = patientDocuments[patientId]?.find(doc => doc.id === documentId);
      if (!doc) {
        console.error('Document not found');
        return;
      }

      // Use the full URL from the database directly
      const documentUrl = doc.filePath;

      // For images, fetch and convert to blob URL for modal viewing
      if (doc.mimeType.startsWith('image/')) {
        // Static files don't need authentication headers
        const response = await fetch(documentUrl);

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

        const blob = await response.blob();
        const url = URL.createObjectURL(blob);
        setViewingDocument({ url, name: doc.originalName });
        setDocumentViewerOpen(true);
      } else {
        // For PDFs and other files, open in new tab
        const link = document.createElement('a');
        link.href = documentUrl;
        link.target = '_blank';
        link.rel = 'noopener noreferrer';
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }
    } catch (error) {
      console.error('Error viewing document:', error);
      toast({
        title: "Error",
        description: "Failed to view document. Please try again.",
        variant: "destructive",
      });
    }
  };

  const handleDownloadDocument = async (documentId: number, patientId: number) => {
    try {
      const doc = patientDocuments[patientId]?.find(doc => doc.id === documentId);
      if (!doc) {
        toast({
          title: "Error",
          description: "Document not found",
          variant: "destructive",
        });
        return;
      }

      // Use the full URL from the database directly
      const documentUrl = doc.filePath;

      // For better download experience, fetch the file and create blob URL
      try {
        const response = await fetch(documentUrl);
        if (!response.ok) {
          throw new Error('Failed to fetch document for download');
        }
        
        const blob = await response.blob();
        const blobUrl = URL.createObjectURL(blob);
        
        // Create a temporary link and trigger download
        const link = document.createElement('a');
        link.href = blobUrl;
        link.download = doc.originalName;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
        
        // Clean up blob URL
        URL.revokeObjectURL(blobUrl);
      } catch (fetchError) {
        // Fallback to direct link if fetch fails
        const link = document.createElement('a');
        link.href = documentUrl;
        link.download = doc.originalName;
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
      }

      toast({
        title: "Success",
        description: "Document downloaded successfully",
      });
    } catch (error) {
      console.error('Error downloading document:', error);
      toast({
        title: "Error",
        description: "Failed to download document. Please try again.",
        variant: "destructive",
      });
    }
  };

  const handleDeleteDocument = async (documentId: number, patientId: number) => {
    try {
      await deleteDocument(documentId);

      // Refresh documents for this patient
      await loadPatientDocuments(patientId);

      toast({
        title: "Document Deleted",
        description: "Document has been deleted successfully",
        variant: "default",
      });
    } catch (error) {
      console.error('Error deleting document:', error);
      toast({
        title: "Error",
        description: error instanceof Error ? error.message : "Failed to delete document",
        variant: "destructive",
      });
    }
  };

  const searchKeyPart = debouncedSearchCriteria?.searchTerm || "recent";

  const {
    data: patientsData,
    isLoading,
    isError,
  } = useQuery<PatientApiResponse, Error>({
    queryKey: qkPatients(currentPage, searchKeyPart),
    queryFn: async () => {
      const trimmedTerm = debouncedSearchCriteria?.searchTerm?.trim();
      const isSearch = trimmedTerm && trimmedTerm.length > 0;

      const rawSearchBy = debouncedSearchCriteria?.searchBy || "name";
      const validSearchKeys = [
        "name",
        "phone",
        "insuranceId",
        "gender",
        "dob",
        "all",
      ];
      const searchKey = validSearchKeys.includes(rawSearchBy)
        ? rawSearchBy
        : "name";

      let url: string;

      if (isSearch) {
        const searchParams = new URLSearchParams({
          limit: String(patientsPerPage),
          offset: String(offset),
        });

        if (searchKey === "all") {
          searchParams.set("term", trimmedTerm!);
        } else {
          searchParams.set(searchKey, trimmedTerm!);
        }

        url = `/api/patients/search?${searchParams.toString()}`;
      } else {
        url = `/api/patients/recent?limit=${patientsPerPage}&offset=${offset}`;
      }

      const res = await apiRequest("GET", url);

      if (!res.ok) {
        const errorData = await res.json();
        throw new Error(errorData.message || "Search failed");
      }

      return res.json();
    },
    placeholderData: {
      patients: [],
      totalCount: 0,
    },
  });

  // Update patient mutation
  const updatePatientMutation = useMutation({
    mutationFn: async ({
      id,
      patient,
    }: {
      id: number;
      patient: UpdatePatient;
    }) => {
      const res = await apiRequest("PUT", `/api/patients/${id}`, patient);
      return res.json();
    },
    onSuccess: async () => {
      setIsAddPatientOpen(false);

      // this query every page,
      await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });
      toast({
        title: "Success",
        description: "Patient updated successfully!",
        variant: "default",
      });
    },
    onError: (error) => {
      toast({
        title: "Error",
        description: `Failed to update patient: ${error.message}`,
        variant: "destructive",
      });
    },
  });

  const deletePatientMutation = useMutation({
    mutationFn: async (id: number) => {
      const res = await apiRequest("DELETE", `/api/patients/${id}`);
      return;
    },
    onSuccess: async () => {
      setIsDeletePatientOpen(false);
      await queryClient.invalidateQueries({ queryKey: QK_PATIENTS_BASE });

      toast({
        title: "Success",
        description: "Patient deleted successfully!",
        variant: "default",
      });
    },
    onError: (error) => {
      console.log(error);
      toast({
        title: "Error",
        description: `Failed to delete patient: ${error.message}`,
        variant: "destructive",
      });
    },
  });

  const handleUpdatePatient = (patient: UpdatePatient & { id?: number }) => {
    if (currentPatient && user) {
      const { id, ...sanitizedPatient } = patient;
      updatePatientMutation.mutate({
        id: Number(currentPatient.id),
        patient: sanitizedPatient,
      });
    } else {
      console.error("No current patient or user found for update");
      toast({
        title: "Error",
        description: "Cannot update patient: No patient or user found",
        variant: "destructive",
      });
    }
  };

  const handleEditPatient = (patient: Patient) => {
    setCurrentPatient(patient);
    setIsAddPatientOpen(true);
  };

  const handleViewPatient = (patient: Patient) => {
    setCurrentPatient(patient);
    setIsViewPatientOpen(true);
  };

  const handleDeletePatient = (patient: Patient) => {
    setCurrentPatient(patient);
    setIsDeletePatientOpen(true);
  };

  const handleConfirmDeletePatient = async () => {
    if (currentPatient) {
      deletePatientMutation.mutate(Number(currentPatient.id));
    } else {
      toast({
        title: "Error",
        description: "No patient selected for deletion.",
        variant: "destructive",
      });
    }
  };

  useEffect(() => {
    if (onPageChange) onPageChange(currentPage);
  }, [currentPage, onPageChange]);

  useEffect(() => {
    const term = debouncedSearchCriteria?.searchTerm?.trim() || "recent";
    if (onSearchChange) onSearchChange(term);
  }, [debouncedSearchCriteria, onSearchChange]);

  const totalPages = useMemo(
    () => Math.ceil((patientsData?.totalCount || 0) / patientsPerPage),
    [patientsData]
  );
  const startItem = offset + 1;
  const endItem = Math.min(
    offset + patientsPerPage,
    patientsData?.totalCount || 0
  );

  const getInitials = (firstName: string, lastName: string) => {
    return (firstName.charAt(0) + lastName.charAt(0)).toUpperCase();
  };

  const getAvatarColor = (id: number) => {
    const colorClasses = [
      "bg-blue-500",
      "bg-teal-500",
      "bg-amber-500",
      "bg-rose-500",
      "bg-indigo-500",
      "bg-green-500",
      "bg-purple-500",
    ];
    return colorClasses[id % colorClasses.length];
  };

  return (
    <div className="bg-white shadow rounded-lg overflow-hidden">
      {/* Selection Panel */}
      {!!selectedPatientId && (
        <div className="bg-red-50 border border-red-200 rounded-tl-md rounded-tr-md px-4 py-3 flex items-center justify-between">
          <div className="flex items-center space-x-2">
            <span className="text-sm font-medium text-red-800">
              1 patient selected
            </span>
          </div>
          <div className="flex items-center space-x-2">
            <Button
              variant="outline"
              size="sm"
              onClick={() => handleScanDocument(selectedPatientId)}
              className="flex items-center space-x-1 text-white bg-green-600 hover:bg-green-500 hover:text-white transition-all duration-300 ease-in-out"
            >
              <Camera className="h-4 w-4" />
              <span>Scan Document</span>
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={handleUploadFiles}
              className="flex items-center space-x-1 bg-blue-500 text-white hover:bg-blue-400 hover:text-white transition-all duration-300 ease-in-out"
            >
              <Upload className="h-4 w-4" />
              <span>Upload Files</span>
            </Button>
            <Button
              variant="outline"
              size="sm"
              onClick={handleClearSelection}
              className="flex items-center space-x-1 border-red-300 text-red-700 hover:bg-red-100 transition-all duration-300 ease-in-out"
            >
              <X className="h-4 w-4" />
              <span>Clear selection</span>
            </Button>
          </div>
        </div>
      )}

      <div className="overflow-x-auto">
        <PatientSearch
          onSearch={(criteria) => {
            setSearchCriteria(criteria);
            setCurrentPage(1); // reset page on new search
            setIsSearchActive(true);
          }}
          onClearSearch={() => {
            setSearchCriteria({ searchTerm: "", searchBy: "name" }); // triggers `recent`
            setCurrentPage(1);
            setIsSearchActive(false);
          }}
          isSearchActive={isSearchActive}
        />
        <Table>
          <TableHeader>
            <TableRow>
              {allowCheckbox && <TableHead>Select</TableHead>}
              <TableHead>Patient</TableHead>
              <TableHead>DOB / Gender</TableHead>
              {/*<TableHead>Contact</TableHead>*/}
              <TableHead>Insurance</TableHead>
              <TableHead>Status</TableHead>
              <TableHead className="text-right">Actions</TableHead>
            </TableRow>
          </TableHeader>
          <TableBody>
            {isLoading ? (
              <TableRow>
                <TableCell
                  colSpan={6}
                  className="text-center py-8 text-muted-foreground"
                >
                  <LoadingScreen />
                </TableCell>
              </TableRow>
            ) : isError ? (
              <TableRow>
                <TableCell
                  colSpan={6}
                  className="text-center py-8 text-red-500"
                >
                  Error loading patients.
                </TableCell>
              </TableRow>
            ) : patientsData?.patients.length === 0 ? (
              <TableRow>
                <TableCell
                  colSpan={6}
                  className="text-center py-8 text-muted-foreground"
                >
                  No patients found.
                </TableCell>
              </TableRow>
            ) : (
              patientsData?.patients.map((patient) => (
                <React.Fragment key={patient.id}>
                  <TableRow className="hover:bg-gray-50">
                    {allowCheckbox && (
                      <TableCell>
                        <Checkbox
                          checked={selectedPatientId === patient.id}
                          onCheckedChange={() => handleSelectPatient(patient)}
                        />
                      </TableCell>
                    )}

                    <TableCell>
                      <div className="flex items-center">
                        <Avatar
                          className={`h-10 w-10 ${getAvatarColor(Number(patient.id))}`}
                        >
                          <AvatarFallback className="text-white">
                            {getInitials(patient.firstName, patient.lastName)}
                          </AvatarFallback>
                        </Avatar>

                        <div className="ml-4">
                          <div className="text-sm font-medium text-gray-900">
                            {patient.firstName} {patient.lastName}
                          </div>
                          <div className="text-sm text-gray-500">
                            PID-{patient.id?.toString().padStart(4, "0")}
                          </div>
                        </div>
                      </div>
                    </TableCell>
                    <TableCell>
                      <div className="text-sm text-gray-900">
                        {formatDateToHumanReadable(patient.dateOfBirth)}
                      </div>
                      <div className="text-sm text-gray-500 capitalize">
                        {patient.gender}
                      </div>
                    </TableCell>
                    {/*<TableCell>
                      <div className="text-sm text-gray-900">{patient.phone}</div>
                      <div className="text-sm text-gray-500">{patient.email}</div>
                    </TableCell>*/}
                    <TableCell>
                      <div className="text-sm text-gray-900">
                        {patient.insuranceProvider ?? "Not specified"}
                      </div>
                      {patient.insuranceId && (
                        <div className="text-sm text-gray-500">
                          ID: {patient.insuranceId}
                        </div>
                      )}
                    </TableCell>
                    <TableCell>
                      <div className="col-span-1">
                        {patient.status === "ACTIVE" && (
                          <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-100 text-green-800">
                            Active
                          </span>
                        )}

                        {patient.status === "INACTIVE" && (
                          <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-red-100 text-red-800">
                            Inactive
                          </span>
                        )}

                        {patient.status === "UNKNOWN" && (
                          <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-gray-200 text-gray-700">
                            Unknown
                          </span>
                        )}

                        {patient.status === "PLAN_NOT_ACCEPTED" && (
                          <span className="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-amber-100 text-amber-800">
                            Plan Not Accepted
                          </span>
                        )}
                      </div>
                    </TableCell>

                    <TableCell className="text-right">
                      <div className="flex justify-end">
                        {allowDelete && isAdmin && (
                          <Button
                            onClick={() => {
                              handleDeletePatient(patient);
                            }}
                            className="text-red-600 hover:text-red-900"
                            aria-label="Delete Patient"
                            variant="ghost"
                            size="icon"
                            title="Delete Patient"
                          >
                            <Delete />
                          </Button>
                        )}
                        {allowFinancial && (
                          <Button
                            variant="ghost"
                            size="icon"
                            onClick={() => {
                              setModalPatientId(Number(patient.id));
                              setIsFinancialsOpen(true);
                            }}
                            className="text-indigo-600 hover:text-indigo-800 hover:bg-indigo-50"
                            title="View financials"
                          >
                            <FileCheck className="h-5 w-5" />
                          </Button>
                        )}
                        {allowEdit && (
                          <Button
                            variant="ghost"
                            size="icon"
                            onClick={() => {
                              handleEditPatient(patient);
                            }}
                            className="text-blue-600 hover:text-blue-800 hover:bg-blue-50"
                            title="Edit Patient"
                          >
                            <Edit className="h-4 w-4" />
                          </Button>
                        )}
                        {allowNewClaim && (
                          <Button
                            variant="ghost"
                            size="icon"
                            onClick={() => onNewClaim?.(Number(patient.id))}
                            className="text-green-600 hover:text-green-800 hover:bg-green-50"
                            title="New Claim"
                          >
                            <FileCheck className="h-5 w-5" />
                          </Button>
                        )}
                        {allowView && (
                          <Button
                            variant="ghost"
                            size="icon"
                            onClick={() => {
                              handleViewPatient(patient);
                            }}
                            className="text-gray-600 hover:text-gray-800 hover:bg-gray-50"
                            title="View Patient Info"
                          >
                            <Eye className="h-4 w-4" />
                          </Button>
                        )}
                      </div>
                    </TableCell>
                  </TableRow>
                </React.Fragment>
              ))
            )}
          </TableBody>
        </Table>
      </div>

      {/* View Patient Modal */}
      <Dialog open={isViewPatientOpen} onOpenChange={setIsViewPatientOpen}>
        <DialogContent className="sm:max-w-[600px]">
          <DialogHeader>
            <DialogTitle>Patient Details</DialogTitle>
            <DialogDescription>
              Complete information about the patient.
            </DialogDescription>
          </DialogHeader>

          {currentPatient && (
            <div className="space-y-4">
              <div className="flex items-center space-x-4">
                <div className="h-16 w-16 rounded-full bg-primary text-white flex items-center justify-center text-xl font-medium">
                  {currentPatient.firstName.charAt(0)}
                  {currentPatient.lastName.charAt(0)}
                </div>
                <div>
                  <h3 className="text-xl font-semibold">
                    {currentPatient.firstName} {currentPatient.lastName}
                  </h3>
                  <p className="text-gray-500">
                    Patient ID: {currentPatient.id?.toString().padStart(4, "0")}
                  </p>
                </div>
              </div>

              <div className="grid grid-cols-1 md:grid-cols-2 gap-4 pt-4">
                <div>
                  <h4 className="font-medium text-gray-900">
                    Personal Information
                  </h4>
                  <div className="mt-2 space-y-2">
                    <p>
                      <span className="text-gray-500">Date of Birth:</span>{" "}
                      {formatDateToHumanReadable(currentPatient.dateOfBirth)}
                    </p>
                    <p>
                      <span className="text-gray-500">Gender:</span>{" "}
                      {currentPatient.gender.charAt(0).toUpperCase() +
                        currentPatient.gender.slice(1)}
                    </p>
                    <p>
                      <span className="text-gray-500">Status:</span>{" "}
                      <span
                        className={cn(
                          currentPatient.status === "ACTIVE"
                            ? "text-green-600"
                            : currentPatient.status === "INACTIVE"
                              ? "text-red-600"
                              : currentPatient.status === "PLAN_NOT_ACCEPTED"
                                ? "text-amber-600"
                                : "text-gray-600",
                          "font-medium"
                        )}
                      >
                        {currentPatient.status === "PLAN_NOT_ACCEPTED"
                          ? "Plan Not Accepted"
                          : currentPatient.status
                            ? currentPatient.status.charAt(0).toUpperCase() +
                            currentPatient.status.slice(1).toLowerCase()
                            : "Unknown"}
                      </span>
                    </p>
                  </div>
                </div>

                <div>
                  <h4 className="font-medium text-gray-900">
                    Contact Information
                  </h4>
                  <div className="mt-2 space-y-2">
                    <p>
                      <span className="text-gray-500">Phone:</span>{" "}
                      {currentPatient.phone}
                    </p>
                    <p>
                      <span className="text-gray-500">Email:</span>{" "}
                      {currentPatient.email || "N/A"}
                    </p>
                    <p>
                      <span className="text-gray-500">Address:</span>{" "}
                      {currentPatient.address ? (
                        <>
                          {currentPatient.address}
                          {currentPatient.city && `, ${currentPatient.city}`}
                          {currentPatient.zipCode &&
                            ` ${currentPatient.zipCode}`}
                        </>
                      ) : (
                        "N/A"
                      )}
                    </p>
                  </div>
                </div>

                <div>
                  <h4 className="font-medium text-gray-900">Insurance</h4>
                  <div className="mt-2 space-y-2">
                    <p>
                      <span className="text-gray-500">Provider:</span>{" "}
                      {currentPatient.insuranceProvider
                        ? currentPatient.insuranceProvider === "delta"
                          ? "Delta Dental"
                          : currentPatient.insuranceProvider === "metlife"
                            ? "MetLife"
                            : currentPatient.insuranceProvider === "cigna"
                              ? "Cigna"
                              : currentPatient.insuranceProvider === "aetna"
                                ? "Aetna"
                                : currentPatient.insuranceProvider
                        : "N/A"}
                    </p>
                    <p>
                      <span className="text-gray-500">ID:</span>{" "}
                      {currentPatient.insuranceId || "N/A"}
                    </p>
                    <p>
                      <span className="text-gray-500">Group Number:</span>{" "}
                      {currentPatient.groupNumber || "N/A"}
                    </p>
                    <p>
                      <span className="text-gray-500">Policy Holder:</span>{" "}
                      {currentPatient.policyHolder || "Self"}
                    </p>
                  </div>
                </div>

                <div>
                  <h4 className="font-medium text-gray-900">
                    Medical Information
                  </h4>
                  <div className="mt-2 space-y-2">
                    <p>
                      <span className="text-gray-500">Allergies:</span>{" "}
                      {currentPatient.allergies || "None reported"}
                    </p>
                    <p>
                      <span className="text-gray-500">Medical Conditions:</span>{" "}
                      {currentPatient.medicalConditions || "None reported"}
                    </p>
                  </div>
                </div>
              </div>

              <div className="flex justify-end space-x-2 pt-4">
                <Button
                  variant="outline"
                  onClick={() => setIsViewPatientOpen(false)}
                >
                  Close
                </Button>
                <Button
                  onClick={() => {
                    setIsViewPatientOpen(false);
                    handleEditPatient(currentPatient);
                  }}
                >
                  Edit Patient
                </Button>
              </div>
            </div>
          )}
        </DialogContent>
      </Dialog>

      {/* Add/Edit Patient Modal */}
      <AddPatientModal
        open={isAddPatientOpen}
        onOpenChange={setIsAddPatientOpen}
        onSubmit={handleUpdatePatient}
        isLoading={isLoading}
        patient={currentPatient}
      />

      {/* Financial Modal */}
      <PatientFinancialsModal
        patientId={modalPatientId}
        open={isFinancialsOpen}
        onOpenChange={(v) => {
          setIsFinancialsOpen(v);
          if (!v) setModalPatientId(null);
        }}
      />

      <DeleteConfirmationDialog
        isOpen={isDeletePatientOpen}
        onConfirm={handleConfirmDeletePatient}
        onCancel={() => setIsDeletePatientOpen(false)}
        entityName={currentPatient?.firstName}
      />

      {/* Pagination */}
      {totalPages > 1 && (
        <div className="bg-white px-4 py-3 border-t border-gray-200">
          <div className="flex flex-col sm:flex-row sm:items-center sm:justify-between">
            <div className="text-sm text-muted-foreground mb-2 sm:mb-0 whitespace-nowrap">
              Showing {startItem}–{endItem} of {patientsData?.totalCount || 0}{" "}
              results
            </div>
            <Pagination>
              <PaginationContent>
                <PaginationItem>
                  <PaginationPrevious
                    href="#"
                    onClick={(e) => {
                      e.preventDefault();
                      if (currentPage > 1) setCurrentPage(currentPage - 1);
                    }}
                    className={
                      currentPage === 1 ? "pointer-events-none opacity-50" : ""
                    }
                  />
                </PaginationItem>

                {getPageNumbers(currentPage, totalPages).map((page, idx) => (
                  <PaginationItem key={idx}>
                    {page === "..." ? (
                      <span className="px-2 text-gray-500">...</span>
                    ) : (
                      <PaginationLink
                        href="#"
                        onClick={(e) => {
                          e.preventDefault();
                          setCurrentPage(page as number);
                        }}
                        isActive={currentPage === page}
                      >
                        {page}
                      </PaginationLink>
                    )}
                  </PaginationItem>
                ))}

                <PaginationItem>
                  <PaginationNext
                    href="#"
                    onClick={(e) => {
                      e.preventDefault();
                      if (currentPage < totalPages)
                        setCurrentPage(currentPage + 1);
                    }}
                    className={
                      currentPage === totalPages
                        ? "pointer-events-none opacity-50"
                        : ""
                    }
                  />
                </PaginationItem>
              </PaginationContent>
            </Pagination>
          </div>
        </div>
      )}

      {/* Document Viewer Modal */}
      <Dialog open={documentViewerOpen} onOpenChange={handleDocumentViewerClose}>
        <DialogContent className="sm:max-w-[50vw] sm:max-h-[90vh]">
          <DialogHeader className="flex flex-row items-center justify-between">
            <div className="flex flex-col">
              <DialogTitle>Document Viewer</DialogTitle>
              <DialogDescription>
                Viewing: {viewingDocument?.name}
              </DialogDescription>
            </div>
            <Button
              variant="ghost"
              size="icon"
              onClick={handleDocumentViewerClose}
              className="h-8 w-8 p-0"
            >
              <X className="h-4 w-4" />
            </Button>
          </DialogHeader>
          <div className="flex flex-col items-center justify-center min-h-[60vh]">
            {viewingDocument && (
              <>
                {viewingDocument.name.toLowerCase().endsWith('.pdf') ? (
                  <iframe
                    src={viewingDocument.url}
                    className="w-full h-[60vh] border rounded"
                    title={viewingDocument.name}
                  />
                ) : viewingDocument.name.toLowerCase().match(/\.(jpg|jpeg|png|gif|webp)$/i) ? (
                  <img
                    src={viewingDocument.url}
                    alt={viewingDocument.name}
                    className="max-w-full max-h-[60vh] object-contain rounded"
                  />
                ) : (
                  <div className="text-center">
                    <FileText className="h-16 w-16 mx-auto text-gray-400 mb-4" />
                    <p className="text-gray-600 mb-4">Preview not available for this file type</p>
                    <Button
                      onClick={() => {
                        const link = document.createElement('a');
                        link.href = viewingDocument.url;
                        link.target = '_blank';
                        link.click();
                      }}
                      className="bg-blue-600 hover:bg-blue-700"
                    >
                      Open in New Tab
                    </Button>
                  </div>
                )}
              </>
            )}
          </div>
        </DialogContent>
      </Dialog>

      {/* Camera Modal */}
      <Dialog open={cameraOpen} onOpenChange={handleCameraClose}>
        <DialogContent className="p-0 border-none max-w-none w-full h-[100dvh] flex flex-col bg-black overflow-hidden sm:rounded-none">
          {/* Full screen container */}
          <div className="relative flex-1 flex flex-col overflow-hidden">

            {/* Close button at top-right */}
            <Button
              variant="ghost"
              size="icon"
              onClick={handleCameraClose}
              className="absolute top-4 right-4 z-50 h-10 w-10 p-0 text-white bg-black/40 hover:bg-black/60 rounded-full"
            >
              <X className="h-6 w-6" />
            </Button>

            {/* Camera/Image View */}
            <div className="relative flex-1 bg-black flex items-center justify-center overflow-hidden">
              {!capturedImage ? (
                <>
                  <video
                    ref={videoRef}
                    autoPlay
                    playsInline
                    className="w-full h-full object-cover"
                  />
                  <canvas ref={canvasRef} className="hidden" />
                </>
              ) : (
                <img
                  src={capturedImage}
                  alt="Captured"
                  className="w-full h-full object-contain"
                />
              )}
            </div>

            {/* Bottom Controls */}
            <div className="absolute bottom-10 left-0 right-0 px-8 flex items-center justify-center bg-transparent z-40">
              {!capturedImage ? (
                <div className="flex items-center justify-between w-full max-w-sm px-4">
                  {/* Camera Switch */}
                  <Button
                    variant="ghost"
                    size="icon"
                    onClick={toggleFacingMode}
                    className="h-12 w-12 text-white bg-white/20 hover:bg-white/40 rounded-full shadow-lg backdrop-blur-sm"
                  >
                    <RefreshCw className="h-6 w-6" />
                  </Button>

                  {/* Capture Image Icon Button */}
                  <button
                    onClick={capturePhoto}
                    className="h-20 w-20 rounded-full border-4 border-white flex items-center justify-center bg-transparent active:scale-90 transition-all shadow-xl"
                  >
                    <div className="h-14 w-14 rounded-full bg-white flex items-center justify-center">
                      <Camera className="h-8 w-8 text-black" />
                    </div>
                  </button>

                  {/* Spacer for symmetry */}
                  <div className="w-12" />
                </div>
              ) : (
                <div className="flex items-center gap-4 w-full max-w-md justify-center">
                  <Button
                    variant="outline"
                    onClick={retakePhoto}
                    className="flex bg-white/10 text-white border-white/20 hover:bg-white/20 px-6 py-4 rounded-2xl font-semibold backdrop-blur-md"
                  >
                    Retake
                  </Button>
                  <Button
                    onClick={saveCapturedPhoto}
                    className="flex bg-white text-black hover:bg-gray-100 px-6 py-4 rounded-2xl font-semibold shadow-lg"
                  >
                    <Upload className="h-5 w-5 mr-2" />
                    Save
                  </Button>
                </div>
              )}
            </div>
          </div>
        </DialogContent>
      </Dialog>
    </div>
  );
}
