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

import Box from '@material-hu/mui/Box';
import Dialog from '@material-hu/mui/Dialog';
import Stack from '@material-hu/mui/Stack';

import HuSpinner from '@material-hu/components/design-system/ProgressIndicators/Spinner';

import { Document } from 'src/config/react-pdf';

import FooterControls from './FullscreenViewer/FooterControls';
import Header from './FullscreenViewer/Header';
import PageInView from './FullscreenViewer/PageInView';

type Props = {
  open: boolean;
  file: string;
  name?: string;
  headerTitle?: string;
  onDownload: () => void;
  onClose: () => void;
  initialPage?: number;
};

const MAX_ZOOM = 2;
const MIN_ZOOM = 0.5;

const HEADER_HEIGHT_SPACING = 9; // theme.spacing(9) -> 72px
const FOOTER_OFFSET_SPACING = 20; // theme.spacing(20) -> 160px

const FullscreenPdfViewer: FC<Props> = ({
  open,
  onClose,
  file,
  name,
  headerTitle,
  onDownload,
  initialPage = 1,
}) => {
  const [numPages, setNumPages] = useState(0);
  const [pageNumber, setPageNumber] = useState(initialPage);
  const [zoomValue, setZoomValue] = useState(1);
  const [allowInViewUpdates, setAllowInViewUpdates] = useState(false);
  const [isReady, setIsReady] = useState(false);

  const scrollContainerRef = useRef<HTMLDivElement>(null);

  const handleDocumentLoadSuccess = useCallback(
    ({ numPages: pages }: { numPages: number }) => {
      setNumPages(pages);
      // Clamp initial page if it exceeds total pages
      setPageNumber(prev => Math.min(Math.max(prev || 1, 1), pages));
    },
    [],
  );

  // Ensure initial scroll to target page when content is ready
  const didInitialScrollRef = useRef(false);
  const ensureInitialScroll = (page: number, attempts = 60) => {
    if (didInitialScrollRef.current) return;
    const container = scrollContainerRef.current;
    const el = document.getElementById(`fs-pdf-page-${page}`);
    if (container && el && el.getBoundingClientRect().height > 0) {
      const containerRect = container.getBoundingClientRect();
      const elRect = el.getBoundingClientRect();
      const offset = elRect.top - containerRect.top + container.scrollTop;
      const top = offset - container.clientHeight / 2 + elRect.height / 2;
      container.scrollTo({ top, behavior: 'auto' });
      didInitialScrollRef.current = true;
      setAllowInViewUpdates(true);
      setIsReady(true);
      return;
    }
    if (attempts > 0) {
      requestAnimationFrame(() => ensureInitialScroll(page, attempts - 1));
    } else {
      // Fallback: allow updates even if we couldn't auto-scroll
      setAllowInViewUpdates(true);
      setIsReady(true);
    }
  };

  const zoomIn = () => setZoomValue(prev => Math.min(prev + 0.1, MAX_ZOOM));
  const zoomOut = () => setZoomValue(prev => Math.max(prev - 0.1, MIN_ZOOM));

  useEffect(() => {
    if (open && numPages > 0) {
      const target = Math.min(Math.max(initialPage || 1, 1), numPages);
      setPageNumber(target);
      didInitialScrollRef.current = false;
      setAllowInViewUpdates(false);
      setIsReady(false);
      requestAnimationFrame(() => ensureInitialScroll(target));
    }
  }, [open, numPages, initialPage]);

  // Reset initial scroll flag when closing or changing file
  useEffect(() => {
    if (!open) {
      didInitialScrollRef.current = false;
      setAllowInViewUpdates(false);
      setIsReady(false);
    }
  }, [open]);

  const handlePageRenderSuccess = useCallback(
    (renderedPage: number) => {
      const target = Math.min(Math.max(initialPage || 1, 1), numPages);
      if (renderedPage === target && !didInitialScrollRef.current) {
        // Only try to scroll once our target page has fully rendered
        requestAnimationFrame(() => ensureInitialScroll(target));
      }
    },
    [initialPage, numPages],
  );

  const zoomPercent = useMemo(() => Math.round(zoomValue * 100), [zoomValue]);

  return (
    <Dialog
      open={open}
      onClose={onClose}
      fullScreen
      slotProps={{
        backdrop: {
          sx: { backgroundColor: 'rgba(0, 0, 0, 0.8)' },
        },
      }}
      PaperProps={{
        sx: {
          bgcolor: 'transparent',
        },
      }}
    >
      <Stack
        sx={{
          width: 1,
          height: 1,
          position: 'relative',
        }}
        onClick={onClose}
      >
        <Box onClick={e => e.stopPropagation()}>
          <Header
            title={headerTitle || name || ''}
            onDownload={onDownload}
            onClose={onClose}
          />
        </Box>
        <Box
          sx={{
            position: 'relative',
            flex: 1,
            overflow: 'auto',
            pt: theme => theme.spacing(HEADER_HEIGHT_SPACING),
            pb: theme => theme.spacing(FOOTER_OFFSET_SPACING),
            px: { xs: 2, md: 4 },
            scrollbarWidth: 'thin',
            scrollbarColor: 'rgba(255,255,255,0.4) transparent',
            '&::-webkit-scrollbar': {
              width: 8,
            },
            '&::-webkit-scrollbar-thumb': {
              backgroundColor: 'rgba(255,255,255,0.4)',
              borderRadius: 999,
            },
            '&::-webkit-scrollbar-track': {
              backgroundColor: 'transparent',
            },
          }}
          ref={scrollContainerRef}
        >
          <Stack
            sx={{
              width: '100%',
              minHeight: '100%',
              alignItems: 'center',
              rowGap: theme => theme.spacing(3),
              '& .react-pdf__Document': {
                width: '100%',
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
                rowGap: theme => theme.spacing(3),
              },
            }}
          >
            <Document
              file={file}
              onLoadSuccess={handleDocumentLoadSuccess}
            >
              {Array.from({ length: numPages || 0 }, (_, index) => (
                <Box
                  key={index}
                  id={`fs-pdf-page-${index + 1}`}
                  sx={{ mb: 2 }}
                >
                  <PageInView
                    index={index}
                    zoomValue={zoomValue}
                    onUpdatePageNumber={setPageNumber}
                    root={scrollContainerRef.current}
                    allowInViewUpdates={allowInViewUpdates}
                    onRenderSuccess={handlePageRenderSuccess}
                  />
                </Box>
              ))}
            </Document>
          </Stack>
          {!isReady && (
            <Stack
              sx={{
                position: 'fixed',
                inset: 0,
                alignItems: 'center',
                justifyContent: 'center',
                pointerEvents: 'none',
              }}
            >
              <HuSpinner centered />
            </Stack>
          )}
          {isReady && (
            <Box onClick={e => e.stopPropagation()}>
              <FooterControls
                pageNumber={pageNumber}
                numPages={numPages}
                zoomIn={zoomIn}
                zoomOut={zoomOut}
                zoomPercent={zoomPercent}
                isZoomInDisabled={zoomValue === MAX_ZOOM}
                isZoomOutDisabled={zoomValue === MIN_ZOOM}
              />
            </Box>
          )}
        </Box>
      </Stack>
    </Dialog>
  );
};

export default FullscreenPdfViewer;
