"use client"

import {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
  type CSSProperties,
} from "react"
import { useTheme } from "next-themes"
import {
  emailPreviewBaseCss,
  emailPreviewDarkOverrideCss,
  emailPreviewLightOverrideCss,
  emailPreviewWrapperCss,
} from "@/lib/email-preview-dark-styles"
import {
  prepareEmailHtmlForIframe,
  injectEmailHtmlIntoDocument,
} from "@/lib/mail-html-iframe"
import { buildEmailPreviewCsp } from "@/lib/mail-remote-content"

const EMAIL_PREVIEW_IFRAME_STYLE: CSSProperties = {
  display: "block",
  background: "transparent",
}

function documentIsDark(): boolean {
  return document.documentElement.classList.contains("dark")
}

function measureIframeContentHeight(doc: Document): number {
  const body = doc.body
  const root = doc.documentElement
  if (!body) return 60
  const heights = [
    body.scrollHeight,
    body.offsetHeight,
    root?.scrollHeight ?? 0,
    root?.clientHeight ?? 0,
  ]
  return Math.max(60, ...heights) + 2
}

export function SandboxedContent({
  html,
  blockRemoteContent,
  restrictPopups = false,
  senderEmail,
  cidUrlMap,
}: {
  html: string
  blockRemoteContent: boolean
  restrictPopups?: boolean
  senderEmail?: string
  cidUrlMap?: Record<string, string>
}) {
  const iframeRef = useRef<HTMLIFrameElement>(null)
  const [height, setHeight] = useState(120)

  const sandboxValue = restrictPopups
    ? "allow-same-origin"
    : "allow-same-origin allow-popups"

  const { resolvedTheme } = useTheme()
  const isDark =
    resolvedTheme === "dark" ||
    ((resolvedTheme === "system" || resolvedTheme === undefined) &&
      typeof document !== "undefined" &&
      documentIsDark())

  const parsedEmail = useMemo(
    () =>
      prepareEmailHtmlForIframe(html, {
        blockRemoteContent,
        isDark,
        senderEmail,
        cidUrlMap,
      }),
    [html, blockRemoteContent, isDark, senderEmail, cidUrlMap]
  )

  const themeCss = useMemo(() => {
    if (!blockRemoteContent) return emailPreviewWrapperCss()
    return `${emailPreviewBaseCss(isDark)}${
      isDark ? emailPreviewDarkOverrideCss() : emailPreviewLightOverrideCss()
    }`
  }, [blockRemoteContent, isDark])

  const cspContent = useMemo(
    () => buildEmailPreviewCsp(blockRemoteContent),
    [blockRemoteContent]
  )

  const injectContent = useCallback(() => {
    const iframe = iframeRef.current
    if (!iframe) return

    const doc = iframe.contentDocument
    if (!doc) return

    injectEmailHtmlIntoDocument(doc, {
      csp: cspContent,
      documentBaseHref: parsedEmail.documentBaseHref,
      resolveBaseHref: parsedEmail.resolveBaseHref,
      headMarkup: parsedEmail.headMarkup,
      bodyHtml: parsedEmail.bodyHtml,
      wrapperCss: themeCss,
    })

    const syncHeight = () => {
      const liveDoc = iframe.contentDocument
      if (!liveDoc) return
      const next = measureIframeContentHeight(liveDoc)
      setHeight((prev) => (prev === next ? prev : next))
    }

    const resizeObserver = new ResizeObserver(syncHeight)

    if (doc.body) {
      resizeObserver.observe(doc.body)
      for (const img of doc.images) {
        if (!img.complete) {
          img.addEventListener("load", syncHeight, { once: true })
          img.addEventListener("error", syncHeight, { once: true })
        }
      }
      for (const link of doc.querySelectorAll('link[rel~="stylesheet"]')) {
        link.addEventListener("load", syncHeight, { once: true })
        link.addEventListener("error", syncHeight, { once: true })
      }
      syncHeight()
      requestAnimationFrame(syncHeight)
      setTimeout(syncHeight, 250)
      setTimeout(syncHeight, 1000)
    }

    return () => resizeObserver.disconnect()
  }, [parsedEmail, themeCss, cspContent])

  useEffect(() => {
    const cleanup = injectContent()
    return () => cleanup?.()
  }, [injectContent])

  return (
    <iframe
      key={blockRemoteContent ? "remote-blocked" : "remote-allowed"}
      ref={iframeRef}
      sandbox={sandboxValue}
      title="Contenu du message"
      className="w-full border-0 bg-transparent"
      style={{ ...EMAIL_PREVIEW_IFRAME_STYLE, height: `${height}px` }}
      tabIndex={-1}
    />
  )
}
