import { useEffect, useMemo, useState } from "react";
import { useQuery, useMutation } from "@tanstack/react-query";
import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
} from "@/components/ui/card";
import { Button } from "@/components/ui/button";
import { toast } from "@/hooks/use-toast";
import { apiRequest, queryClient } from "@/lib/queryClient";
import { Eye, Trash, Download, FolderOpen, FileText } from "lucide-react";
import { DeleteConfirmationDialog } from "@/components/ui/deleteDialog";
import { PatientTable } from "@/components/patients/patient-table";
import { Patient, PdfFile } from "@repo/db/types";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "@/components/ui/pagination";
import DocumentsFilePreviewModal from "@/components/documents/file-preview-modal";
import { getPageNumbers } from "@/utils/pageNumberGenerator";
import {
  getPatientDocuments,
  deleteDocument,
  formatFileSize,
  type PatientDocument
} from "@/lib/api/documents";

export default function DocumentsPage() {
  const [selectedPatient, setSelectedPatient] = useState<Patient | null>(null);
  const [expandedGroupId, setExpandedGroupId] = useState<number | null>(null);

  // pagination state for the expanded group
  const [currentPage, setCurrentPage] = useState<number>(1);
  const [limit, setLimit] = useState<number>(5);
  const offset = (currentPage - 1) * limit;
  const [totalForExpandedGroup, setTotalForExpandedGroup] = useState<
    number | null
  >(null);

  const [showPatientDocuments, setShowPatientDocuments] = useState(false);

  // Document preview state
  const [previewDocumentId, setPreviewDocumentId] = useState<number | null>(null);
  const [isPreviewModalOpen, setIsPreviewModalOpen] = useState(false);

  // Delete document state
  const [deleteDocumentId, setDeleteDocumentId] = useState<number | null>(null);
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);

  // PDF state
  const [currentPdf, setCurrentPdf] = useState<PdfFile | null>(null);

  // Delete dialog
  const [isDeletePdfOpen, setIsDeletePdfOpen] = useState(false);

  // reset UI when patient changes
  useEffect(() => {
    setExpandedGroupId(null);
    setLimit(5);
    setCurrentPage(1);
    setTotalForExpandedGroup(null);
    setShowPatientDocuments(false);
    setIsPreviewModalOpen(false);
    setPreviewDocumentId(null);
  }, [selectedPatient]);

  // Patient documents — React Query for caching (re-selecting same patient shows instantly)
  const { data: patientDocuments = [], isLoading: patientDocumentsLoading } =
    useQuery<PatientDocument[]>({
      queryKey: ["patientDocuments", selectedPatient?.id],
      enabled: !!selectedPatient?.id,
      staleTime: 2 * 60 * 1000,
      queryFn: async () => {
        const response = await getPatientDocuments(selectedPatient!.id);
        if (!response.success) throw new Error("Failed to load documents");
        return response.documents;
      },
    });

  // Derive thumbnails synchronously — no extra async round-trip
  const documentThumbnails = useMemo(() => {
    const result: { [key: number]: string } = {};
    for (const doc of patientDocuments) {
      if (doc.mimeType.startsWith("image/")) result[doc.id] = doc.filePath;
    }
    return result;
  }, [patientDocuments]);

  // Listen for document upload events — invalidate React Query cache instead of manual refetch
  useEffect(() => {
    const refresh = () => {
      if (selectedPatient?.id) {
        queryClient.invalidateQueries({ queryKey: ["patientDocuments", selectedPatient.id] });
      }
    };

    window.addEventListener("documentUploaded", refresh);
    const handleStorageChange = (e: StorageEvent) => {
      if (e.key === "documentUploaded" && e.newValue) refresh();
    };
    window.addEventListener("storage", handleStorageChange);

    return () => {
      window.removeEventListener("documentUploaded", refresh);
      window.removeEventListener("storage", handleStorageChange);
    };
  }, [selectedPatient]);

  // Handle document preview
  const handlePreviewDocument = (documentId: number) => {
    const document = patientDocuments.find(doc => doc.id === documentId);
    setPreviewDocumentId(documentId);
    setIsPreviewModalOpen(true);
  };

  // Handle document delete
  const handleDeleteDocument = (documentId: number) => {
    setDeleteDocumentId(documentId);
    setIsDeleteDialogOpen(true);
  };

  // Confirm document delete
  const confirmDeleteDocument = async () => {
    if (!deleteDocumentId) return;

    try {
      const response = await deleteDocument(deleteDocumentId);
      if (response.success) {
        toast({
          title: "Success",
          description: "Document deleted successfully",
        });
        // Reload documents for the current patient
        if (selectedPatient?.id) {
          await loadPatientDocuments(selectedPatient.id);
        }
      } else {
        throw new Error("Failed to delete document");
      }
    } catch (error) {
      console.error("Failed to delete document:", error);
      toast({
        title: "Error",
        description: "Failed to delete document",
        variant: "destructive",
      });
    } finally {
      setIsDeleteDialogOpen(false);
      setDeleteDocumentId(null);
    }
  };

  // FETCH GROUPS for patient (includes `category` on each group)
  const { data: groups = [], isLoading: isLoadingGroups } = useQuery({
    queryKey: ["groups", selectedPatient?.id],
    enabled: !!selectedPatient,
    staleTime: 2 * 60 * 1000,
    queryFn: async () => {
      const res = await apiRequest(
        "GET",
        `/api/documents/pdf-groups/patient/${selectedPatient?.id}`
      );
      return res.json();
    },
  });

  // Group groups by titleKey (use titleKey only for grouping/ordering; don't display it)
  const groupsByTitleKey = useMemo(() => {
    const map = new Map<string, any[]>();
    for (const g of groups as any[]) {
      const key = String(g.titleKey ?? "OTHER");
      if (!map.has(key)) map.set(key, []);
      map.get(key)!.push(g);
    }

    // Decide on a stable order for titleKey buckets: prefer enum order then any extras
    const preferredOrder = [
      "INSURANCE_CLAIM",
      "INSURANCE_CLAIM_PREAUTH",
      "ELIGIBILITY_STATUS",
      "CLAIM_STATUS",
      "OTHER",
    ];
    const orderedKeys: string[] = [];

    for (const k of preferredOrder) {
      if (map.has(k)) orderedKeys.push(k);
    }
    // append any keys that weren't in preferredOrder
    for (const k of map.keys()) {
      if (!orderedKeys.includes(k)) orderedKeys.push(k);
    }

    return { map, orderedKeys };
  }, [groups]);

  // FETCH PDFs for selected group with pagination (limit & offset)
  const {
    data: groupPdfsResponse,
    refetch: refetchGroupPdfs,
    isFetching: isFetchingPdfs,
  } = useQuery({
    queryKey: ["groupPdfs", expandedGroupId, currentPage, limit],
    enabled: !!expandedGroupId,
    queryFn: async () => {
      // API should accept ?limit & ?offset and also return total count
      const res = await apiRequest(
        "GET",
        `/api/documents/recent-pdf-files/group/${expandedGroupId}?limit=${limit}&offset=${offset}`
      );
      // expected shape: { data: PdfFile[], total: number }
      const json = await res.json();
      setTotalForExpandedGroup(json.total ?? null);
      return json.data ?? [];
    },
  });

  const groupPdfs: PdfFile[] = groupPdfsResponse ?? [];

  // DELETE mutation
  const deletePdfMutation = useMutation({
    mutationFn: async (id: number) => {
      await apiRequest("DELETE", `/api/documents/pdf-files/${id}`);
    },
    onSuccess: () => {
      setIsDeletePdfOpen(false);
      setCurrentPdf(null);
      queryClient.invalidateQueries({
        queryKey: ["groupPdfs", expandedGroupId],
      });
      toast({ title: "Success", description: "PDF deleted successfully!" });
    },
    onError: (error: any) => {
      toast({
        title: "Error",
        description: error.message || "Failed to delete PDF",
        variant: "destructive",
      });
    },
  });

  const handleConfirmDeletePdf = () => {
    if (currentPdf) {
      deletePdfMutation.mutate(Number(currentPdf.id));
    } else {
      toast({
        title: "Error",
        description: "No PDF selected for deletion.",
        variant: "destructive",
      });
    }
  };

  const handleViewPdf = (pdfId: number, filename?: string) => {
    setPreviewDocumentId(pdfId);
    setIsPreviewModalOpen(true);
  };

  const handleDownloadPdf = async (pdfId: number, filename: string) => {
    const res = await apiRequest("GET", `/api/documents/pdf-files/${pdfId}`);
    const arrayBuffer = await res.arrayBuffer();
    const blob = new Blob([arrayBuffer], { type: "application/pdf" });
    const url = URL.createObjectURL(blob);
    const a = document.createElement("a");
    a.href = url;
    a.download = filename;
    document.body.appendChild(a);
    a.click();
    document.body.removeChild(a);
    URL.revokeObjectURL(url);
  };

  // Expand / collapse a group — when expanding reset pagination
  const toggleExpandGroup = (groupId: number) => {
    if (expandedGroupId === groupId) {
      setExpandedGroupId(null);
      setCurrentPage(1);
      setLimit(5);
      setTotalForExpandedGroup(null);
    } else {
      setExpandedGroupId(groupId);
      setCurrentPage(1);
      setLimit(5);
      setTotalForExpandedGroup(null);
    }
  };

  // pagintaion helper
  const totalPages = totalForExpandedGroup
    ? Math.ceil(totalForExpandedGroup / limit)
    : 1;

  const startItem = totalForExpandedGroup ? offset + 1 : 0;
  const endItem = totalForExpandedGroup
    ? Math.min(offset + limit, totalForExpandedGroup)
    : 0;

  return (
    <div>
      <div className="container mx-auto space-y-6">
        <div className="flex justify-between items-center">
          <div>
            <h1 className="text-3xl font-bold tracking-tight">Documents</h1>
            <p className="text-muted-foreground">
              View and manage recent uploaded claim PDFs
            </p>
          </div>
        </div>

        {selectedPatient && (
          <Card>
            <CardHeader>
              <CardTitle>
                Document groups of Patient: {selectedPatient.firstName}{" "}
                {selectedPatient.lastName}
              </CardTitle>
            </CardHeader>

            <CardContent className="space-y-4">


              {/* Existing Groups Section */}
              <div>
                {/* <h4 className="text-lg font-semibold mb-3">Document Groups</h4> */}
                {isLoadingGroups ? (
                  <div>Loading groups…</div>
                ) : (groups as any[]).length === 0 && patientDocuments.length === 0 && !patientDocumentsLoading ? (
                  <div className="text-sm text-muted-foreground">
                    No groups found.
                  </div>
                ) : (
                  <div className="flex flex-col gap-3">
                    {groupsByTitleKey.orderedKeys.map((key, idx) => {
                      const bucket = groupsByTitleKey.map.get(key) ?? [];
                      return (
                        <div key={key}>
                          {/* subtle divider between buckets (no enum text shown) */}
                          {idx !== 0 && (
                            <hr className="my-3 border-t border-gray-200" />
                          )}

                          <div className="flex flex-col gap-2">
                            {bucket.map((group: any) => (
                              <div key={group.id} className="border rounded p-3">
                                <div className="flex items-center justify-between">
                                  <div className="flex items-center gap-3">
                                    <FolderOpen className="w-5 h-5" />
                                    <div>
                                      {/* Only show the group's title string */}
                                      <div className="font-semibold">
                                        {group.title}
                                      </div>
                                    </div>
                                  </div>

                                  <div className="flex items-center gap-2">
                                    <Button
                                      size="sm"
                                      variant={
                                        expandedGroupId === group.id
                                          ? "default"
                                          : "outline"
                                      }
                                      onClick={() => toggleExpandGroup(group.id)}
                                    >
                                      {expandedGroupId === group.id
                                        ? "Collapse"
                                        : "Open"}
                                    </Button>
                                  </div>
                                </div>

                                {/* expanded content: show paginated PDFs for this group */}
                                {expandedGroupId === group.id && (
                                  <div className="mt-3 space-y-3">
                                    {isFetchingPdfs ? (
                                      <div>Loading PDFs…</div>
                                    ) : groupPdfs.length === 0 ? (
                                      <div className="text-muted-foreground">
                                        No PDFs in this group.
                                      </div>
                                    ) : (
                                      <div className="flex flex-col gap-2">
                                        {groupPdfs.map((pdf) => (
                                          <div
                                            key={pdf.id}
                                            className="flex justify-between items-center border rounded p-2"
                                          >
                                            <div className="text-sm">
                                              {pdf.filename}
                                            </div>
                                            <div className="flex gap-2">
                                              <Button
                                                variant="ghost"
                                                size="sm"
                                                onClick={() =>
                                                  handleViewPdf(
                                                    Number(pdf.id),
                                                    pdf.filename
                                                  )
                                                }
                                              >
                                                <Eye className="w-4 h-4" />
                                              </Button>
                                              <Button
                                                variant="ghost"
                                                size="sm"
                                                onClick={() =>
                                                  handleDownloadPdf(
                                                    Number(pdf.id),
                                                    pdf.filename
                                                  )
                                                }
                                              >
                                                <Download className="w-4 h-4" />
                                              </Button>
                                              <Button
                                                variant="ghost"
                                                size="sm"
                                                onClick={() => {
                                                  setCurrentPdf(pdf);
                                                  setIsDeletePdfOpen(true);
                                                }}
                                              >
                                                <Trash className="w-4 h-4" />
                                              </Button>
                                            </div>
                                          </div>
                                        ))}

                                        {/* Pagination */}
                                        {totalPages > 1 && (
                                          <div className="bg-white px-4 py-3 border-t border-gray-200 rounded">
                                            <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{" "}
                                                {totalForExpandedGroup || 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>
                                        )}
                                      </div>
                                    )}
                                  </div>
                                )}
                              </div>
                            ))}
                          </div>
                        </div>
                      );
                    })}

                    {/* Patient Documents Section - moved outside groups mapping */}
                    {patientDocuments.length > 0 && (
                      <div>
                        <div>
                          {(groups as any[]).length > 0 && (
                            <hr className="my-3 border-t border-gray-200" />
                          )}
                        </div>
                        <div className="border rounded p-3">
                          <div className="flex items-center justify-between">
                            <div className="flex items-center gap-3">
                              <FolderOpen className="w-5 h-5" />
                              <div>
                                <div className="font-semibold">
                                  Other Documents
                                </div>
                              </div>
                            </div>

                            <Button
                              size="sm"
                              variant={showPatientDocuments ? "default" : "outline"}
                              className="flex items-center gap-2"
                              onClick={() => setShowPatientDocuments(!showPatientDocuments)}
                            >
                              {showPatientDocuments ? (
                                <>
                                  <span className="">Collapse</span>
                                </>
                              ) : (
                                <>
                                  <span>Open</span>
                                </>
                              )}
                            </Button>
                          </div>

                          {showPatientDocuments && (
                            <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4 mt-3">
                              {patientDocuments.map((document: PatientDocument) => (
                                <div
                                  key={document.id}
                                  className="bg-white rounded-lg border border-gray-200 p-4 hover:shadow-md transition-shadow"
                                >
                                  <div className="flex items-start space-x-3">
                                    {/* Thumbnail */}
                                    <div className="flex-shrink-0">
                                      {document.mimeType.startsWith('image/') && documentThumbnails[document.id] ? (
                                        <img
                                          src={documentThumbnails[document.id]}
                                          alt={document.originalName}
                                          className="w-10 h-10 object-cover rounded-lg border border-gray-200"
                                        />
                                      ) : (
                                        <div className="w-10 h-10 bg-gray-100 rounded-lg border border-gray-200 flex items-center justify-center">
                                          {document.mimeType.startsWith('image/') ? (
                                            <div className="animate-spin rounded-full h-6 w-6 border-b-2 border-blue-600"></div>
                                          ) : (
                                            <FileText className="h-6 w-6 text-gray-400" />
                                          )}
                                        </div>
                                      )}
                                    </div>

                                    {/* Document Info */}
                                    <div className="flex-1 min-w-0">
                                      <h4 className="text-sm font-medium text-gray-900 truncate">
                                        {document.originalName}
                                      </h4>
                                      <div className="flex items-center gap-1 mt-1">
                                        <p className="text-xs text-gray-500">
                                          {formatFileSize(document.fileSize)}
                                        </p>
                                        <span className="text-[12px]">|</span>
                                        <div className="flex">
                                          <span className={`inline-flex items-center text-xs font-medium ${document.mimeType.startsWith('image/')
                                            ? 'text-green-800'
                                            : document.mimeType === 'application/pdf'
                                              ? 'text-red-800'
                                              : 'text-blue-800'
                                            }`}>
                                            {document.mimeType.startsWith('image/') ? 'Image' :
                                              document.mimeType === 'application/pdf' ? 'PDF' :
                                                document.mimeType.split('/')[1]?.toUpperCase() || 'File'}
                                          </span>
                                        </div>
                                      </div>
                                    </div>

                                    {/* Actions */}
                                    <div className="flex items-center space-x-1">
                                      <Button
                                        variant="ghost"
                                        size="icon"
                                        onClick={() => handlePreviewDocument(document.id)}
                                        className="h-8 w-8 text-blue-600 hover:text-blue-800 hover:bg-blue-50"
                                        title="View Document"
                                      >
                                        <Eye className="h-4 w-4" />
                                      </Button>
                                      <Button
                                        variant="ghost"
                                        size="icon"
                                        onClick={async () => {
                                          const doc = patientDocuments.find(doc => doc.id === document.id);
                                          if (doc?.filePath) {
                                            try {
                                              // Fetch the file as a blob to force download
                                              const response = await fetch(doc.filePath);
                                              const blob = await response.blob();
                                              const url = window.URL.createObjectURL(blob);
                                              const link = window.document.createElement('a');
                                              link.href = url;
                                              link.download = doc.originalName;
                                              window.document.body.appendChild(link);
                                              link.click();
                                              window.document.body.removeChild(link);
                                              window.URL.revokeObjectURL(url);
                                            } catch (error) {
                                              console.error('Download failed:', error);
                                            }
                                          }
                                        }}
                                        className="h-8 w-8 text-green-600 hover:text-green-800 hover:bg-green-50"
                                        title="Download Document"
                                      >
                                        <Download className="h-4 w-4" />
                                      </Button>
                                      <Button
                                        variant="ghost"
                                        size="icon"
                                        onClick={() => handleDeleteDocument(document.id)}
                                        className="h-8 w-8 text-red-600 hover:text-red-800 hover:bg-red-50"
                                        title="Delete Document"
                                      >
                                        <Trash className="h-4 w-4" />
                                      </Button>
                                    </div>
                                  </div>
                                </div>
                              ))}
                            </div>
                          )}
                        </div>
                      </div>
                    )}
                  </div>
                )}
              </div>
            </CardContent>
          </Card>
        )}

        <Card>
          <CardHeader>
            <CardTitle>Patient Records</CardTitle>
            <CardDescription>
              Select a patient to view document groups
            </CardDescription>
          </CardHeader>
          <CardContent>
            <PatientTable
              allowView
              allowDelete
              allowCheckbox
              allowEdit
              onSelectPatient={setSelectedPatient}
            />
          </CardContent>
        </Card>

        <DeleteConfirmationDialog
          isOpen={isDeletePdfOpen}
          onConfirm={handleConfirmDeletePdf}
          onCancel={() => setIsDeletePdfOpen(false)}
          entityName={`PDF #${currentPdf?.id}`}
        />

        {/* Document Preview Modal */}
        <DocumentsFilePreviewModal
          fileId={previewDocumentId}
          isOpen={isPreviewModalOpen}
          onClose={() => {
            setIsPreviewModalOpen(false);
            setPreviewDocumentId(null);
          }}
          isPatientDocument={patientDocuments.some(doc => doc.id === previewDocumentId)}
          directImageUrl={patientDocuments.find(doc => doc.id === previewDocumentId)?.filePath}
          initialFileName={patientDocuments.find(doc => doc.id === previewDocumentId)?.originalName}
        />

        {/* Document Delete Confirmation Dialog */}
        <DeleteConfirmationDialog
          isOpen={isDeleteDialogOpen}
          onConfirm={confirmDeleteDocument}
          onCancel={() => {
            setIsDeleteDialogOpen(false);
            setDeleteDocumentId(null);
          }}
          entityName={patientDocuments.find(doc => doc.id === deleteDocumentId)?.originalName || `Document #${deleteDocumentId}`}
        />
      </div>
    </div>
  );
}
