import { cn } from "@/lib/utils";
import { Button } from "@/ui";
import { useResizeObserver } from "@wojtekmaj/react-hooks";
import { t } from "i18next";
import { ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
import { useCallback, useMemo, useState } from "react";
import { Document, Page, pdfjs } from "react-pdf";
import { LoadingSpinner } from "../LoadingSpinner";

import "react-pdf/dist/esm/Page/AnnotationLayer.css";
import "react-pdf/dist/esm/Page/TextLayer.css";

/*pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  "pdfjs-dist/build/pdf.worker.min.mjs",
  import.meta.url
).toString();*/

pdfjs.GlobalWorkerOptions.workerSrc = `//unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`;

const maxWidth = 800;
const resizeObserverOptions = {};

export interface PDFViewerProps {
  file?:
    | string
    | {
        data: Uint8Array;
      };
  onThumbnailClick?: () => void;
  className?: string;
}

export const PDFViewer = ({ file, onThumbnailClick, className }: PDFViewerProps): JSX.Element => {
  const [numPages, setNumPages] = useState<number>(0);
  const [pageNumber, setPageNumber] = useState<number>(1);
  const [renderedPageNumber, setRenderedPageNumber] = useState<number | undefined>(undefined);

  const [containerRef, setContainerRef] = useState<HTMLElement | null>(null);
  const [containerWidth, setContainerWidth] = useState<number>();

  const onResize = useCallback<ResizeObserverCallback>((entries) => {
    const [entry] = entries;

    if (entry) {
      setContainerWidth(entry.contentRect.width);
    }
  }, []);

  useResizeObserver(containerRef, resizeObserverOptions, onResize);

  const onPageRenderSuccess = useCallback(() => {
    setRenderedPageNumber(pageNumber);
  }, [setRenderedPageNumber, pageNumber]);

  function onDocumentLoadSuccess({ numPages }: { numPages: number }) {
    setPageNumber(1);
    setNumPages(numPages);
  }

  const changePage = useCallback(
    (offset: number) =>
      setPageNumber((prevPage) =>
        offset > 0 ? Math.min(prevPage + offset, numPages) : Math.max(prevPage + offset, 1)
      ),
    [numPages]
  );

  const goToNextPage = useCallback(() => changePage(1), [changePage]);
  const goToPrevPage = useCallback(() => changePage(-1), [changePage]);
  //const goToFirstPage = useCallback(() => setPageNumber(1), [setPageNumber]);
  //const goToLastPage = useCallback(() => setPageNumber(numPages), [setPageNumber, numPages]);

  const isLoading = useMemo(
    () => renderedPageNumber !== pageNumber,
    [renderedPageNumber, pageNumber]
  );

  const options = useMemo(
    () => ({
      cMapUrl: "/cmaps/",
      standardFontDataUrl: "/standard_fonts/",
    }),
    []
  );

  return (
    <div
      className={cn("flex flex-col cursor-default text-center", className)}
      ref={setContainerRef}
    >
      <Document
        file={file}
        onLoadSuccess={onDocumentLoadSuccess}
        loading={<LoadingSpinner className='w-full mx-auto mt-32' />}
        options={options}
        className={cn(
          `w-full aspect-[3/4] relative bg-white shadow w-[${
            containerWidth ? Math.min(containerWidth, maxWidth) : maxWidth
          }]`,
          onThumbnailClick ? "cursor-pointer" : ""
        )}
      >
        {/**
         * IMPORTANT: Keys are necessary so that React will know which Page component
         * instances to use.
         * Without keys, on page number update, React would replace the page number
         * in 1st and 2nd page components. This may cause previously rendered page
         * to render again, thus causing a flash.
         * With keys, React, will add prevPage className to previously rendered page,
         * and mount new Page component instance for the new page.
         */}

        <Page
          className={isLoading && renderedPageNumber ? "visible" : "hidden"}
          key={`page_${renderedPageNumber}`}
          pageNumber={renderedPageNumber}
          canvasBackground={"white"}
          width={containerWidth ? Math.min(containerWidth, maxWidth) : maxWidth}
          onClick={() => (onThumbnailClick ? onThumbnailClick() : null)}
        />

        <Page
          className={cn(isLoading && renderedPageNumber ? "hidden" : "visible", "text-center")}
          key={pageNumber}
          pageNumber={pageNumber}
          canvasBackground={"white"}
          onRenderSuccess={onPageRenderSuccess}
          width={containerWidth ? Math.min(containerWidth, maxWidth) : maxWidth}
          onClick={() => (onThumbnailClick ? onThumbnailClick() : null)}
        />
      </Document>

      {/* <Pagination className='w-auto ml-auto mr-0'>
        <PaginationContent>
          <PaginationItem>
            <Button size='icon' variant='outline' className='w-6 h-6'>
              <ChevronLeftIcon className='h-3.5 w-3.5' />
              <span className='sr-only'>Previous Order</span>
            </Button>
          </PaginationItem>
          <PaginationItem>
            <Button size='icon' variant='outline' className='w-6 h-6'>
              <ChevronRightIcon className='h-3.5 w-3.5' />
              <span className='sr-only'>Next Order</span>
            </Button>
          </PaginationItem>
        </PaginationContent>
      </Pagination>*/}

      <div className='flex flex-row justify-center w-full mt-4 space-x-4'>
        <Button
          type='button'
          variant='outline'
          className='w-8 h-8 p-0'
          onClick={goToPrevPage}
          disabled={isLoading}
        >
          <span className='sr-only'>{t("common.go_to_prev_page")}</span>
          <ChevronLeftIcon className='w-4 h-4' />
        </Button>
        <Button
          type='button'
          variant='outline'
          className='w-8 h-8 p-0'
          onClick={goToNextPage}
          disabled={isLoading}
        >
          <span className='sr-only'>{t("common.go_to_next_page")}</span>
          <ChevronRightIcon className='w-4 h-4' />
        </Button>
      </div>
      <p className='mt-4 text-sm font-medium text-center'>
        {t("common.num_page_of_total", {
          count: pageNumber,
          total: numPages,
        })}
      </p>
    </div>
  );
};
