import {
  type MouseEvent,
  useCallback,
  useEffect,
  useRef,
  useState,
} from 'react';

import Spinner from '@design-system/ProgressIndicators/Spinner';
import { usePdfDimensions } from '@hooks/usePdfDimensions';
import { Stack } from '@mui/material';
import { Document } from '@src/config/react-pdf';
import { downloadUrl } from '@src/utils/files';
import { times } from 'lodash';

import { MIN_FULLSCREEN_ZOOM } from '../../constants';
import { getFile } from '../../utils';
import FileDialog from '../FileDialog';
import Header from '../Header';
import PdfPage from '../Page';
import PdfTools from '../Tools';

import { type PdfFullScreenProps } from './types';
import { isClickingInsidePdf } from './utils';

export const PdfFullScreen = ({
  file,
  name,
  onClose,
  showHeader = false,
  slotProps = {},
  fileProps,
}: PdfFullScreenProps) => {
  const [numPages, setNumPages] = useState(0);
  const [pageNumber, setPageNumber] = useState(1);
  const [isLoading, setIsLoading] = useState(true);
  const [zoom, setZoom] = useState(MIN_FULLSCREEN_ZOOM);
  const [showButtons, setShowButtons] = useState(true);

  const timerRef = useRef<ReturnType<typeof setTimeout>>();
  const dialogRef = useRef(null);
  const documentRef = useRef(null);

  const { dimensions: pageDimensions, handleLoadPage } = usePdfDimensions(
    documentRef.current,
  );

  const handleResetTimeout = () => {
    setShowButtons(true);
    clearTimeout(timerRef.current);
    timerRef.current = setTimeout(() => setShowButtons(false), 3000);
  };

  useEffect(() => {
    setNumPages(0);
    setPageNumber(1);
    setZoom(MIN_FULLSCREEN_ZOOM);
  }, [file]);

  useEffect(() => {
    window.addEventListener('mousemove', handleResetTimeout);

    return () => {
      window.removeEventListener('mousemove', handleResetTimeout);
      clearTimeout(timerRef.current);
    };
  }, []);

  const handleLoadSuccess = ({ numPages: newNumPages }: any) => {
    setNumPages(newNumPages);
    setIsLoading(false);
  };

  const handleZoom = (newZoom: number) => setZoom(newZoom);

  const handleClose = () => {
    setPageNumber(1);
    setZoom(MIN_FULLSCREEN_ZOOM);
    onClose();
  };

  const handleDownload = (event: MouseEvent) => {
    event.preventDefault();
    event.stopPropagation();
    downloadUrl(file, name);
  };

  const handleUpdatePageNumber = useCallback((newPageNumber: number) => {
    handleResetTimeout();
    setPageNumber(newPageNumber);
  }, []);

  const handleClickOutside = (event: MouseEvent<HTMLDivElement>) => {
    const target = event.target as HTMLElement;

    if (isClickingInsidePdf(target)) {
      return;
    }

    handleClose();
  };

  const pdfFile = getFile(file);

  return (
    <FileDialog
      open
      onClose={handleClose}
      onClick={handleClickOutside}
      ref={dialogRef}
      maxWidth="lg"
    >
      {showHeader && (
        <Header
          name={name}
          onClose={handleClose}
          onDownload={handleDownload}
          {...slotProps.header}
        />
      )}
      <Stack
        ref={documentRef}
        sx={{
          width: '100%',
          height: '100vh',
          display: 'flex',
          justifyContent: 'center',
          alignItems: 'center',
        }}
      >
        <>
          {fileProps?.isLoading && <Spinner />}
          <div style={{ display: fileProps?.isLoading ? 'none' : 'flex' }}>
            <Document
              file={pdfFile}
              onLoadSuccess={handleLoadSuccess}
              inputRef={documentRef}
              loading={<Spinner />}
              externalLinkTarget="_blank"
            >
              {times(numPages, index => (
                <PdfPage
                  key={index}
                  page={index + 1}
                  zoom={zoom}
                  onUpdatePageNumber={handleUpdatePageNumber}
                  onLoadSuccess={handleLoadPage}
                  dimensions={pageDimensions}
                />
              ))}
            </Document>
          </div>
        </>
      </Stack>
      {showButtons && (
        <PdfTools
          loading={isLoading}
          pageNumber={pageNumber}
          totalPages={numPages}
          zoom={zoom}
          onZoom={handleZoom}
        />
      )}
    </FileDialog>
  );
};

export default PdfFullScreen;
