import React, { useMemo } from 'react'

import CarouselNav from './CarouselNav'
import { filenameFromUrl } from './fileMeta'
import { useCarousel } from './useCarousel'
import ViewerShell from './ViewerShell'

export interface PdfViewerItem {
  /** Source URL of the PDF document. */
  src: string
  /** Filename used as the dialog's accessible name. */
  filename?: string
}

export interface PdfViewerProps {
  open: boolean
  items: PdfViewerItem[]
  /** Index to display when the viewer first opens. Defaults to `0`. */
  initialIndex?: number
  onClose: () => void
}

/**
 * Modal PDF viewer that hosts the active document inside a sandboxed
 * `<iframe>`, leaving native rendering, scroll, search, and the
 * browser's built-in download controls to the browser. The lightbox
 * chrome is intentionally just a close button plus, for stacked
 * attachments, carousel prev/next + counter.
 */
const PdfViewer: React.FC<PdfViewerProps> = ({
  open,
  items,
  initialIndex = 0,
  onClose,
}) => {
  const { index, prev, next } = useCarousel({
    length: items.length,
    initialIndex,
    open,
  })

  const item = items[index]
  const filename = useMemo(
    () => item?.filename ?? (item ? filenameFromUrl(item.src) : 'document'),
    [item]
  )

  // `#toolbar=0` is honored by Chromium-family browsers and hides the
  // built-in PDF toolbar's redundant controls. Firefox / Safari ignore
  // it and keep their native toolbars, which is fine — the user gets a
  // familiar experience either way.
  //
  // Preserve any existing fragment the caller supplied (e.g.
  // `#page=3`) by merging our params into it rather than naively
  // appending a second `#…` segment.
  const iframeSrc = useMemo(
    () => (item ? withPdfViewerParams(item.src) : undefined),
    [item]
  )

  if (!item || !iframeSrc) return null

  return (
    <ViewerShell
      open={open}
      onClose={onClose}
      ariaLabel={filename}
      counter={items.length > 1 ? `${index + 1} / ${items.length}` : undefined}
      data-testid="pdf-viewer"
    >
      <iframe
        // Force a key swap on item change so the iframe remounts a
        // fresh document rather than re-using the previous scroll
        // position / search state when the user navigates between
        // siblings.
        key={`${index}:${item.src}`}
        src={iframeSrc}
        title={filename}
        className="block h-[calc(100dvh-128px)] w-[min(96vw,1400px)] border-0 bg-white"
        // Sandbox the iframe to stop the embedded document from
        // reaching parent context. We intentionally omit
        // `allow-same-origin`: even when the PDF host happens to share
        // our origin, granting it defeats the rest of the sandbox.
        // `allow-scripts` keeps the native PDF viewer's interactive
        // affordances (search, page nav, form filling) working,
        // `allow-downloads` lets the user save via the built-in
        // toolbar where it's still visible (Firefox / Safari), and
        // `allow-popups` lets external links inside the PDF open in a
        // new tab.
        sandbox="allow-scripts allow-forms allow-popups allow-downloads"
      />

      {items.length > 1 ? (
        <CarouselNav
          onPrev={prev}
          onNext={next}
          prevLabel="Previous document"
          nextLabel="Next document"
        />
      ) : null}
    </ViewerShell>
  )
}

/**
 * Merge our PDF-viewer params (`toolbar=0`, `navpanes=0`) into the
 * URL's existing fragment so callers can still pass things like
 * `#page=3` without us clobbering them — naively appending
 * `#toolbar=0` to a URL that already has a fragment produces
 * `…#page=3#toolbar=0` which most readers ignore.
 */
const withPdfViewerParams = (src: string): string => {
  const hashIndex = src.indexOf('#')
  const base = hashIndex === -1 ? src : src.slice(0, hashIndex)
  const existing = hashIndex === -1 ? '' : src.slice(hashIndex + 1)

  const params = new URLSearchParams(existing)
  if (!params.has('toolbar')) params.set('toolbar', '0')
  if (!params.has('navpanes')) params.set('navpanes', '0')

  return `${base}#${params.toString()}`
}

export default PdfViewer
