<script lang="ts">
  import { onDestroy } from "svelte";
  import { browser } from "$app/environment";

  export let src: string | null = null;

  let container: HTMLDivElement;
  let pageCount = 0;
  let loading = true;
  let error = "";

  let pdfjsLib: typeof import("pdfjs-dist") | null = null;
  let currentPdf: any = null;
  let currentSrc: string | null = null;
  let renderGeneration = 0;

  // Max canvas dimension to prevent browser OOM
  const MAX_CANVAS_DIM = 2048;

  async function initPdfJs() {
    if (!browser || pdfjsLib) return;
    const lib = await import("pdfjs-dist");
    // Use fake worker to avoid worker-loading issues with Vite/SvelteKit
    lib.GlobalWorkerOptions.workerSrc = new URL(
      "pdfjs-dist/build/pdf.worker.min.mjs",
      import.meta.url,
    ).toString();
    pdfjsLib = lib;
  }

  async function renderPdf(pdfSrc: string) {
    if (!pdfSrc || !container || !browser) return;

    // Set currentSrc immediately to prevent re-entry
    currentSrc = pdfSrc;
    const generation = ++renderGeneration;
    loading = true;
    error = "";

    // Clean up previous PDF
    if (currentPdf) {
      currentPdf.destroy();
      currentPdf = null;
    }
    container.innerHTML = "";

    try {
      await initPdfJs();
      if (!pdfjsLib || generation !== renderGeneration) return;

      const pdf = await pdfjsLib.getDocument({
        url: pdfSrc,
        isEvalSupported: false,
      }).promise;
      if (generation !== renderGeneration) {
        pdf.destroy();
        return;
      }
      currentPdf = pdf;
      pageCount = pdf.numPages;

      for (let i = 1; i <= pageCount; i++) {
        if (generation !== renderGeneration) return;

        const page = await pdf.getPage(i);

        // Calculate a safe scale that won't exceed MAX_CANVAS_DIM
        const baseViewport = page.getViewport({ scale: 1.0 });
        const maxDim = Math.max(baseViewport.width, baseViewport.height);
        const safeScale =
          maxDim > MAX_CANVAS_DIM ? MAX_CANVAS_DIM / maxDim : 1.0;
        const viewport = page.getViewport({ scale: safeScale });

        const canvas = document.createElement("canvas");
        canvas.className = "pdf-viewer-page";
        canvas.width = viewport.width;
        canvas.height = viewport.height;
        canvas.addEventListener("contextmenu", (e) => e.preventDefault());
        container.appendChild(canvas);

        const canvasContext = canvas.getContext("2d")!;
        await page.render({ canvasContext, viewport }).promise;

        // Release page resources after rendering
        page.cleanup();
      }
    } catch (err: unknown) {
      if (generation === renderGeneration) {
        error = err instanceof Error ? err.message : "Failed to render PDF";
        console.error("PDF render error:", err);
      }
    } finally {
      if (generation === renderGeneration) {
        loading = false;
      }
    }
  }

  function cleanup() {
    renderGeneration++;
    if (currentPdf) {
      currentPdf.destroy();
      currentPdf = null;
    }
    currentSrc = null;
  }

  // React to src changes (also handles initial render once container is bound)
  $: if (browser && src && src !== currentSrc && container) {
    renderPdf(src);
  }

  // Handle no-src case
  $: if (browser && !src) {
    loading = false;
  }

  onDestroy(() => {
    cleanup();
  });
</script>

<div class="pdf-viewer" on:contextmenu|preventDefault role="document">
  {#if loading}
    <div class="pdf-viewer-loading">
      <p>Rendering PDF...</p>
    </div>
  {/if}

  {#if error}
    <div class="pdf-viewer-error">
      <p>{error}</p>
    </div>
  {/if}

  <div class="pdf-viewer-pages" bind:this={container}></div>
</div>

<style>
  .pdf-viewer {
    width: 100%;
    height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    background: var(--bg-surface-raised, #2a2a2a);
    -webkit-user-select: none;
    user-select: none;
  }

  .pdf-viewer-pages {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 8px;
  }

  .pdf-viewer-pages :global(.pdf-viewer-page) {
    max-width: 100%;
    border-radius: 2px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.3);
  }

  .pdf-viewer-loading,
  .pdf-viewer-error {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    font-size: 12px;
    color: var(--text-muted, #888);
    font-style: italic;
  }
</style>
