"use client";

import { useEffect, useMemo, useState } from "react";
import { Document, Page, pdfjs } from "react-pdf";

// Use bundled worker (avoid CDN + CORS issues).
pdfjs.GlobalWorkerOptions.workerSrc = new URL(
  "pdfjs-dist/build/pdf.worker.min.mjs",
  import.meta.url,
).toString();

export type PdfViewerBox = {
  id: string;
  label?: string;
  // PDF coordinate space (points), origin=BOTTOMLEFT (Docling-style)
  bbox: [number, number, number, number]; // [l, t, r, b]
  color?: string;
};

export type PdfViewerProps = {
  fileUrl: string;
  /** 1-based */
  pageNumber: number;
  scale?: number;
  className?: string;
  /** (Not used in demo mode) */
  showAllPages?: boolean;
  /** Called after PDF loads with total pages. */
  onNumPages?: (numPages: number) => void;

  boxes?: PdfViewerBox[];
  showBoxes?: boolean;
};

export function PdfViewerImpl({
  fileUrl,
  pageNumber,
  scale = 1.25,
  className,
  showAllPages = false, // kept for API compatibility
  onNumPages,
  boxes,
  showBoxes = false,
}: PdfViewerProps) {
  const [numPages, setNumPages] = useState<number | null>(null);
  const [pageProxy, setPageProxy] = useState<any>(null);
  const [visibleIds, setVisibleIds] = useState<Record<string, boolean>>({});

  const safePage = useMemo(() => {
    const p = Number.isFinite(pageNumber) ? Math.floor(pageNumber) : 1;
    if (!numPages) return Math.max(1, p);
    return Math.min(Math.max(1, p), numPages);
  }, [pageNumber, numPages]);

  useEffect(() => {
    // Force recalculation of viewport when selected page changes.
    setPageProxy(null);
  }, [safePage, scale]);

  // Initialize/reset visibility when boxes change.
  useEffect(() => {
    if (!boxes?.length) {
      setVisibleIds({});
      return;
    }
    setVisibleIds((prev) => {
      const next: Record<string, boolean> = {};
      for (const b of boxes) {
        next[b.id] = prev[b.id] ?? true;
      }
      return next;
    });
  }, [boxes]);

  const viewport = useMemo(() => {
    if (!pageProxy) return null;
    try {
      // PDF.js viewport coordinates are TOPLEFT (CSS pixels).
      return pageProxy.getViewport({ scale });
    } catch {
      return null;
    }
  }, [pageProxy, scale]);

  const rects = useMemo(() => {
    if (!showBoxes || !boxes?.length || !viewport) return [];

    // Docling bbox is in PDF point-space with origin=BOTTOMLEFT.
    // pdf.js expects PDF point-space; convertToViewportPoint returns TOPLEFT pixels.
    return boxes.map((b) => {
      const [l, t, r, bb] = b.bbox;
      const [x1, y1] = viewport.convertToViewportPoint(l, t);
      const [x2, y2] = viewport.convertToViewportPoint(r, bb);
      const left = Math.min(x1, x2);
      const top = Math.min(y1, y2);
      const width = Math.abs(x2 - x1);
      const height = Math.abs(y2 - y1);
      return {
        ...b,
        left,
        top,
        width,
        height,
      };
    });
  }, [boxes, showBoxes, viewport]);

  const anyBoxes = Boolean(boxes?.length);
  const allVisible = useMemo(() => {
    if (!boxes?.length) return false;
    return boxes.every((b) => visibleIds[b.id] !== false);
  }, [boxes, visibleIds]);

  return (
    <div className={className}>
      <Document
        file={fileUrl}
        onLoadSuccess={(pdf) => {
          setNumPages(pdf.numPages);
          onNumPages?.(pdf.numPages);
        }}
        loading={<div className="text-sm text-muted-foreground">Loading PDF…</div>}
        error={<div className="text-sm text-red-600">Failed to load PDF.</div>}
      >
        {showBoxes && anyBoxes ? (
          <div className="mb-2 flex flex-wrap items-center gap-3 text-xs">
            <label className="inline-flex select-none items-center gap-2">
              <input
                type="checkbox"
                checked={allVisible}
                onChange={(e) => {
                  const checked = e.target.checked;
                  setVisibleIds((prev) => {
                    const next = { ...prev };
                    for (const b of boxes ?? []) next[b.id] = checked;
                    return next;
                  });
                }}
              />
              Show boxes
            </label>
            {boxes?.map((b) => (
              <label key={b.id} className="inline-flex select-none items-center gap-2">
                <input
                  type="checkbox"
                  checked={visibleIds[b.id] !== false}
                  onChange={(e) => {
                    const checked = e.target.checked;
                    setVisibleIds((prev) => ({ ...prev, [b.id]: checked }));
                  }}
                />
                <span className="inline-flex items-center gap-2">
                  <span
                    className="h-2.5 w-2.5 rounded-sm"
                    style={{ backgroundColor: b.color ?? "#ef4444" }}
                  />
                  {b.label ?? b.id}
                </span>
              </label>
            ))}
          </div>
        ) : null}

        <div className="relative inline-block">
          <Page
            pageNumber={safePage}
            scale={scale}
            renderAnnotationLayer={false}
            renderTextLayer={false}
            onLoadSuccess={(loadedPage) => setPageProxy(loadedPage)}
          />

          {showBoxes && viewport && rects.length ? (
            <div
              className="absolute left-0 top-0"
              style={{
                width: viewport.width,
                height: viewport.height,
                pointerEvents: "none",
              }}
            >
              {rects
                .filter((r) => visibleIds[r.id] !== false)
                .map((r) => (
                  <div
                    key={r.id}
                    style={{
                      position: "absolute",
                      left: r.left,
                      top: r.top,
                      width: r.width,
                      height: r.height,
                      border: `2px solid ${r.color ?? "#ef4444"}`,
                      background: "rgba(239, 68, 68, 0.08)",
                      boxSizing: "border-box",
                    }}
                  >
                    {r.label ? (
                      <div
                        style={{
                          position: "absolute",
                          left: 0,
                          top: 0,
                          transform: "translateY(-100%)",
                          background: r.color ?? "#ef4444",
                          color: "white",
                          fontSize: 10,
                          lineHeight: "14px",
                          padding: "1px 4px",
                          borderRadius: 4,
                          whiteSpace: "nowrap",
                        }}
                      >
                        {r.label}
                      </div>
                    ) : null}
                  </div>
                ))}
            </div>
          ) : null}
        </div>
      </Document>

      {numPages ? (
        <div className="mt-2 text-xs text-muted-foreground">
          Page {safePage} / {numPages}
        </div>
      ) : null}
    </div>
  );
}

