import { ElementType, lazy, memo, Suspense } from 'react'
import classNames from 'classnames'
import PdfViewer from './pdf-viewer'
import { FullSizeLoadingSpinner } from '../../../shared/components/loading-spinner'
import { useDetachCompileContext as useCompileContext } from '../../../shared/context/detach-compile-context'
import { PdfPreviewMessages } from './pdf-preview-messages'
import CompileTimeWarningUpgradePrompt from './compile-time-warning-upgrade-prompt'
import { PdfPreviewProvider } from './pdf-preview-provider'
import PdfPreviewHybridToolbar from '@/features/pdf-preview/components/pdf-preview-hybrid-toolbar'
import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
import PdfCodeCheckFailedBanner from '@/features/pdf-preview/components/pdf-code-check-failed-banner'
import getMeta from '@/utils/meta'
import PdfLogsViewer from '@/features/pdf-preview/components/pdf-logs-viewer'

const TypstWasmPreview = lazy(
  () =>
    import(
      /* webpackChunkName: "typst-wasm-preview" */
      '@/features/typst-preview/components/typst-wasm-preview'
    )
)

function PdfPreviewPane() {
  const {
    pdfUrl,
    pdfViewer,
    darkModePdf: darkModeSetting,
    activeOverallTheme,
    isTypstProject,
    typstPreviewMode,
  } = useCompileContext()
  const { compileTimeout } = getMeta('ol-compileSettings')
  const isHtmlOutput = pdfUrl?.includes('output.html')
  const darkModePdf =
    (pdfViewer === 'pdfjs' || isHtmlOutput) &&
    activeOverallTheme === 'dark' &&
    darkModeSetting

  const isWasmMode = isTypstProject && typstPreviewMode === 'wasm'
  const classes = classNames('pdf', 'full-size', {
    'pdf-empty': !pdfUrl && !isWasmMode,
    'pdf-dark-mode': darkModePdf,
  })

  const pdfPromotions = importOverleafModules('pdfPreviewPromotions') as {
    import: { default: ElementType }
    path: string
  }[]

  return (
    <div className={classes}>
      <PdfPreviewProvider>
        <PdfPreviewHybridToolbar />
        <PdfCodeCheckFailedBanner />
        <PdfPreviewMessages>
          {compileTimeout < 60 && <CompileTimeWarningUpgradePrompt />}
        </PdfPreviewMessages>
        <Suspense fallback={<FullSizeLoadingSpinner delay={500} />}>
          <div className="pdf-viewer" data-testid="pdf-viewer">
            {isWasmMode ? (
              <TypstWasmPreview />
            ) : (
              <PdfViewer />
            )}
          </div>
        </Suspense>
        <PdfLogsViewer />
        {pdfPromotions.map(({ import: { default: Component }, path }) => (
          <Component key={path} />
        ))}
      </PdfPreviewProvider>
    </div>
  )
}

export default memo(PdfPreviewPane)
