import { useEffect, useRef, type RefObject } from "react";
import { pdfjs, type PdfDocumentProxy } from "@/utils/pdfjsSetup";
import type { PdfRect } from "@/utils/pdfAnchor";
import { highlightBackgroundStyle } from "@/constants/bookmarkHighlightColors";

interface PdfHighlightOverlay {
  rects: PdfRect[];
  color: string;
}

interface PdfViewerProps {
  document: PdfDocumentProxy;
  pageNumber: number;
  scale: number;
  highlights?: PdfHighlightOverlay[];
  pageWrapRef?: RefObject<HTMLDivElement | null>;
}

export function PdfViewer({
  document,
  pageNumber,
  scale,
  highlights = [],
  pageWrapRef,
}: PdfViewerProps) {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  const textLayerRef = useRef<HTMLDivElement>(null);
  const internalWrapRef = useRef<HTMLDivElement>(null);
  const wrapRef = pageWrapRef ?? internalWrapRef;
  const renderTaskRef = useRef<{ cancel: () => void } | null>(null);

  useEffect(() => {
    let cancelled = false;

    async function renderPage() {
      if (renderTaskRef.current) {
        renderTaskRef.current.cancel();
        renderTaskRef.current = null;
      }

      const canvas = canvasRef.current;
      const textLayer = textLayerRef.current;
      if (!canvas || !textLayer) return;

      try {
        const page = await document.getPage(pageNumber);
        if (cancelled) return;

        const viewport = page.getViewport({ scale });
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        textLayer.style.width = `${viewport.width}px`;
        textLayer.style.height = `${viewport.height}px`;
        textLayer.innerHTML = "";

        const ctx = canvas.getContext("2d");
        if (!ctx) return;

        const renderTask = page.render({ canvasContext: ctx, viewport });
        renderTaskRef.current = renderTask;
        await renderTask.promise;
        if (cancelled) return;

        const textContent = await page.getTextContent();
        const textTask = (
          pdfjs as typeof pdfjs & {
            renderTextLayer: (params: {
              textContentSource: typeof textContent;
              container: HTMLDivElement;
              viewport: typeof viewport;
            }) => { promise: Promise<void> };
          }
        ).renderTextLayer({
          textContentSource: textContent,
          container: textLayer,
          viewport,
        });
        await textTask.promise;
      } catch {
        if (!cancelled) {
          textLayerRef.current && (textLayerRef.current.innerHTML = "");
        }
      }
    }

    void renderPage();

    return () => {
      cancelled = true;
      if (renderTaskRef.current) {
        renderTaskRef.current.cancel();
        renderTaskRef.current = null;
      }
    };
  }, [document, pageNumber, scale]);

  return (
    <div ref={wrapRef} className="pdf-page-wrap">
      <canvas ref={canvasRef} className="pdf-page-canvas" />
      <div ref={textLayerRef} className="pdf-text-layer" />
      <div className="pdf-highlight-layer" aria-hidden>
        {highlights.flatMap((hl, hi) =>
          hl.rects.map((rect, ri) => {
            const [x, y, w, h] = rect;
            return (
              <div
                key={`${hi}-${ri}`}
                className="pdf-highlight-rect"
                style={{
                  left: `${x * 100}%`,
                  top: `${y * 100}%`,
                  width: `${w * 100}%`,
                  height: `${h * 100}%`,
                  ...highlightBackgroundStyle(hl.color),
                }}
              />
            );
          }),
        )}
      </div>
    </div>
  );
}
