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

import Stack from '@material-hu/mui/Stack';
import { type FileAsset } from '@material-hu/types/attachments';

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

import { Document } from 'src/config/react-pdf';
import { type SectionComponent } from 'src/pages/dashboard/serviceManagement/types';

import { usePdfCompletion } from '../contexts/PdfFormCompletionProvider';

import PdfPageWithOverlay from './PdfPageWithOverlay';

type Props = {
  pdfFileAsset: FileAsset;
  fieldsPerPage: Record<number, SectionComponent[]> | undefined;
};

const PdfDocumentForm: FC<Props> = ({ fieldsPerPage, pdfFileAsset }) => {
  const contentRef = useRef<HTMLDivElement | null>(null);
  const [hasHOverflow, setHasHOverflow] = useState(false);

  const {
    totalPages,
    scrollContainerRef,
    registerPageRef,
    setCurrentPageInView,
    setPdfDimensionsMetadata,
    pdfDimensionsMetadata,
  } = usePdfCompletion();

  // Measure horizontal overflow to switch alignment dynamically
  useEffect(() => {
    const container = scrollContainerRef.current;
    const content = contentRef.current;
    if (!container || !content) return;

    const measure = () => {
      // Compare content width vs container viewport width
      const overflow = content.scrollWidth > container.clientWidth;
      setHasHOverflow(overflow);
    };

    // Initial measure
    const rafId = requestAnimationFrame(measure);

    // Observe both container and content for size changes
    const ro = new ResizeObserver(measure);
    ro.observe(container);
    ro.observe(content);

    window.addEventListener('resize', measure);
    return () => {
      window.removeEventListener('resize', measure);
      ro.disconnect();
      cancelAnimationFrame(rafId);
    };
  }, [scrollContainerRef]);

  const handleLoadSuccess = (loadedPdf: {
    numPages: number;
    getPage: (pageNumber: number) => Promise<any>;
  }) =>
    (async () => {
      // For each page we store the dimensions
      const results: {
        pageNumber: number;
        width: number;
        height: number;
      }[] = await Promise.all(
        Array.from({ length: loadedPdf.numPages }, async (_, i) => {
          const page = await loadedPdf.getPage(i + 1);
          const vp1 = page.getViewport({ scale: 1, rotation: 0 });
          return {
            pageNumber: i + 1,
            width: vp1.width,
            height: vp1.height,
          };
        }),
      );

      setPdfDimensionsMetadata({
        totalPages: loadedPdf.numPages,
        pageDimensions: results,
      });
    })();

  // Track current page in view based on scroll within the container
  useEffect(() => {
    const container = scrollContainerRef.current;
    const content = contentRef.current;
    if (!container || !content) return;

    const handleScroll = () => {
      const containerTop = container.scrollTop;
      const containerHeight = container.clientHeight;
      const containerCenter = containerTop + containerHeight / 2;

      let bestIndex = 0;
      let bestDistance = Number.POSITIVE_INFINITY;
      const children = content.children;
      for (let i = 0; i < children.length; i++) {
        const el = children[i] as HTMLElement;
        const center = el.offsetTop + el.offsetHeight / 2;
        const dist = Math.abs(center - containerCenter);
        if (dist < bestDistance) {
          bestDistance = dist;
          bestIndex = i;
        }
      }
      setCurrentPageInView(bestIndex + 1);
    };

    handleScroll();
    container.addEventListener('scroll', handleScroll, { passive: true });

    const ro = new ResizeObserver(handleScroll);
    ro.observe(container);
    ro.observe(content);

    return () => {
      container.removeEventListener('scroll', handleScroll);
      ro.disconnect();
    };
  }, [scrollContainerRef, contentRef, totalPages, setCurrentPageInView]);

  if (!pdfFileAsset) return null;

  return (
    <Stack
      sx={{
        flex: 1,
        minHeight: 0,
        width: 1,
      }}
    >
      <Stack
        sx={{
          width: '100%',
          flex: 1,
          px: 1,
          overflow: 'auto',
          alignItems: hasHOverflow ? 'flex-start' : 'center',
          minHeight: 0,
          minWidth: 0,
        }}
        ref={scrollContainerRef}
      >
        <Document
          file={pdfFileAsset.url}
          onLoadSuccess={handleLoadSuccess}
          loading={<HuSpinner centered />}
        >
          <Stack
            sx={{
              gap: 2, // Spacing between pages
              py: 4,
              alignItems: 'flex-start',
              width: 'max-content',
            }}
            ref={contentRef}
          >
            {Array.from({ length: totalPages }, (_, i) => (
              <PdfPageWithOverlay
                key={i}
                pageIndex={i}
                ref={el => registerPageRef(i, el)}
                fields={fieldsPerPage?.[i + 1] || []}
                pageDimensions={
                  pdfDimensionsMetadata?.pageDimensions?.[i] || {
                    pageNumber: i + 1,
                    width: 0,
                    height: 0,
                  }
                }
              />
            ))}
          </Stack>
        </Document>
      </Stack>
    </Stack>
  );
};

export default PdfDocumentForm;
