'use client'

import { useEffect, useRef, useState } from 'react'
import { useDebounce, useSize } from 'ahooks'
import { useVirtualizer } from '@tanstack/react-virtual'
import type { pdfjs as PdfJsType } from 'react-pdf'
import 'react-pdf/dist/Page/TextLayer.css'
import 'react-pdf/dist/Page/AnnotationLayer.css'

type ReactPdfModule = typeof import('react-pdf')

type PdfComponents = {
  Document: ReactPdfModule['Document'] | null
  Page: ReactPdfModule['Page'] | null
  pdfjs: ReactPdfModule['pdfjs'] | null
}

type PdfLike = {
  numPages: number
  getPage: (pageNumber: number) => Promise<{ view: number[] }>
}

function useReactPdf() {
  const [components, setComponents] = useState<PdfComponents>({
    Document: null,
    Page: null,
    pdfjs: null,
  })

  useEffect(() => {
    // 仅在浏览器环境下加载 react-pdf，避免 Node.js 中触发 pdf.js 的 DOM 依赖
    if (typeof window === 'undefined') return

    let cancelled = false

    ;(async () => {
      try {
        const mod: ReactPdfModule = await import('react-pdf')

        if (cancelled) return

        const { Document, Page, pdfjs } = mod

        // 配置 pdf.js worker
        ;(pdfjs as typeof PdfJsType).GlobalWorkerOptions.workerSrc =
          `https://unpkg.com/pdfjs-dist@${pdfjs.version}/build/pdf.worker.min.mjs`

        setComponents({
          Document,
          Page,
          pdfjs,
        })
      } catch (error) {
        console.error('Failed to load react-pdf:', error)
      }
    })()

    return () => {
      cancelled = true
    }
  }, [])

  return components
}

export function VirtualPdfPreview({ url }: { url: string }) {
  const [numPages, setNumPages] = useState<number | null>(null)
  const [renderedPages, setRenderedPages] = useState<number[]>([])
  const [pageHeight, setPageHeight] = useState(0)
  const [aspectRatio, setAspectRatio] = useState(0)
  const [errorText, setErrorText] = useState<string | null>(null)

  const wrapperRef = useRef<HTMLDivElement>(null)
  const parentRef = useRef<HTMLDivElement>(null)
  const oldPageHeight = useRef(0)

  const size = useSize(wrapperRef)
  const containerWidth = useDebounce(size?.width, { wait: 200 })

  const { Document, Page } = useReactPdf()

  const virtualizer = useVirtualizer({
    count: numPages || 0,
    getScrollElement: () => parentRef.current,
    estimateSize: () => (pageHeight || 800) + 10,
    overscan: 4,
    enabled: !!pageHeight,
  })

  useEffect(() => {
    setRenderedPages([])
    setErrorText(null)
  }, [containerWidth, url])

  useEffect(() => {
    if (containerWidth && aspectRatio) {
      virtualizer.shouldAdjustScrollPositionOnItemSizeChange = () => false
      const newHeight = !aspectRatio || !containerWidth ? 800 : containerWidth / aspectRatio
      const lastPageIndex = oldPageHeight.current
        ? Number(virtualizer.scrollOffset ?? 0) / oldPageHeight.current
        : 0

      setPageHeight(newHeight)
      oldPageHeight.current = newHeight
      virtualizer.measure()

      if (parentRef.current) {
        setTimeout(() => {
          parentRef.current?.scrollTo({
            top: lastPageIndex * newHeight,
            behavior: 'auto',
          })
        }, 100)
      }
    }
  }, [containerWidth, aspectRatio, virtualizer])

  const onDocumentLoadSuccess = async (pdf: PdfLike) => {
    setErrorText(null)
    setNumPages(pdf.numPages)
    const pageObj = await pdf.getPage(1)
    const pageWidth = pageObj.view[2]
    const firstPageHeight = pageObj.view[3]
    const ratio = Number((pageWidth / firstPageHeight).toFixed(2))
    setAspectRatio(ratio)
    setRenderedPages([])
  }

  const handlePageRenderSuccess = (pageNumber: number) => {
    setRenderedPages(prev => (prev.includes(pageNumber) ? prev : [...prev, pageNumber]))
  }

  if (errorText) {
    return (
      <div className="h-full w-full flex items-center justify-center text-sm text-destructive px-4 text-center">
        PDF 预览加载失败：{errorText}
      </div>
    )
  }

  // 浏览器端尚未加载到 react-pdf，给一个轻量的占位
  if (!Document || !Page) {
    return (
      <div className="h-full w-full flex items-center justify-center text-sm text-muted-foreground px-4 text-center">
        正在加载 PDF 预览组件...
      </div>
    )
  }

  return (
    <div ref={wrapperRef} className="w-full h-full mt-[80px]">
      <div
        ref={parentRef}
        className="h-full overflow-scroll [&_.react-pdf__message.react-pdf__message--loading]:h-full [&::-webkit-scrollbar]:hidden scroll-smooth [-webkit-overflow-scrolling:touch]"
      >
        <Document
          file={url}
          loading={
            <div className="h-full w-full flex items-center justify-center text-sm text-muted-foreground">
              PDF 加载中...
            </div>
          }
          onLoadError={(error) => {
            console.error('react-pdf load failed:', error)
            setErrorText(error instanceof Error ? error.message : '未知错误')
          }}
          onLoadSuccess={onDocumentLoadSuccess}
        >
          <div
            style={{
              height: `${virtualizer.getTotalSize()}px`,
              width: '100%',
              position: 'relative',
            }}
          >
            {virtualizer.getVirtualItems().map(virtualRow => (
              <div
                key={virtualRow.index}
                style={{
                  position: 'absolute',
                  top: 0,
                  left: 0,
                  width: '100%',
                  transform: `translateY(${virtualRow.start}px)`,
                }}
                className="w-full flex justify-center duration-200 transition-transform"
              >
                {!renderedPages.includes(virtualRow.index + 1) && (
                  <div
                    className="absolute top-0 left-0 right-0 z-1 flex items-center justify-center bg-card/94 text-sm text-muted-foreground duration-200 transition-transform backdrop-blur-sm"
                    style={{
                      height: `${pageHeight}px`,
                    }}
                  >
                    PDF 渲染中...
                  </div>
                )}
                <Page
                  loading={
                    <div className="h-full w-full flex items-center justify-center text-sm text-muted-foreground">
                      PDF 渲染中...
                    </div>
                  }
                  pageNumber={virtualRow.index + 1}
                  width={containerWidth}
                  onRenderSuccess={() => {
                    handlePageRenderSuccess(virtualRow.index + 1)
                  }}
                />
              </div>
            ))}
          </div>
        </Document>
      </div>
    </div>
  )
}
