"use client"

import { memo, useEffect, useRef, useState } from "react"
import { EditorContent, type Editor } from "@tiptap/react"
import type { DocPageLayout } from "@/lib/drive/doc-page-setup"
import { cn } from "@/lib/utils"
import { focusEditorAtPointer } from "@/lib/drive/focus-editor-at-pointer"

const PAGE_GAP_PX = 12

/** Actual block layout height — ignores CSS min-height on ProseMirror (page stack). */
function measureProseContentHeight(prose: HTMLElement): number {
  if (prose.childElementCount === 0) {
    return 0
  }
  let maxBottom = 0
  for (const child of prose.children) {
    const el = child as HTMLElement
    maxBottom = Math.max(maxBottom, el.offsetTop + el.offsetHeight)
  }
  return maxBottom
}

function DocsPageViewInner({
  editor,
  pageLayout,
  zoom,
  editable,
  onPageCountChange,
}: {
  editor: Editor
  pageLayout: DocPageLayout
  zoom: number
  editable: boolean
  onPageCountChange?: (count: number) => void
}) {
  const pageWidth = pageLayout.widthPx
  const pageHeight = pageLayout.heightPx
  const margins = pageLayout.marginsPx
  const canvasRef = useRef<HTMLDivElement>(null)
  const contentRef = useRef<HTMLDivElement>(null)
  const [pageCount, setPageCount] = useState(1)
  const [narrowViewport, setNarrowViewport] = useState(false)
  const onPageCountChangeRef = useRef(onPageCountChange)
  onPageCountChangeRef.current = onPageCountChange

  const scale = zoom / 100
  const scaledWidth = pageWidth * scale

  useEffect(() => {
    const canvas = canvasRef.current
    if (!canvas) return

    const syncViewport = () => {
      setNarrowViewport(canvas.clientWidth < scaledWidth)
    }

    syncViewport()
    const ro = new ResizeObserver(syncViewport)
    ro.observe(canvas)
    return () => ro.disconnect()
  }, [scaledWidth])

  useEffect(() => {
    const surface = contentRef.current
    if (!surface) return

    let rafId = 0

    const measure = () => {
      const prose = surface.querySelector(".ProseMirror") as HTMLElement | null
      if (!prose) return

      const contentHeight = measureProseContentHeight(prose)
      const paddedHeight = margins.top + margins.bottom + contentHeight
      const count = Math.max(1, Math.ceil(paddedHeight / pageHeight))
      setPageCount((prev) => (prev === count ? prev : count))
    }

    const scheduleMeasure = () => {
      if (rafId) cancelAnimationFrame(rafId)
      rafId = requestAnimationFrame(measure)
    }

    scheduleMeasure()
    const prose = surface.querySelector(".ProseMirror") as HTMLElement | null
    const ro = prose ? new ResizeObserver(scheduleMeasure) : null
    if (prose && ro) ro.observe(prose)

    const onTransaction = () => scheduleMeasure()
    editor.on("transaction", onTransaction)

    return () => {
      if (rafId) cancelAnimationFrame(rafId)
      ro?.disconnect()
      editor.off("transaction", onTransaction)
    }
  }, [margins.bottom, margins.top, pageHeight, editor])

  useEffect(() => {
    onPageCountChangeRef.current?.(pageCount)
  }, [pageCount])

  const stackHeight = pageCount * pageHeight + (pageCount - 1) * PAGE_GAP_PX
  const innerMinHeight = Math.max(pageHeight - margins.top - margins.bottom, stackHeight - margins.top - margins.bottom)
  const scaledHeight = stackHeight * scale
  const verticalPadding = narrowViewport ? 32 : 64
  const textAreaBorderCss = pageLayout.textAreaBorderCss
  const sheetBorderCss = pageLayout.sheetBorderCss
  const pageBackground = pageLayout.pageColor
  const backgroundLayers = pageLayout.pageBackgroundLayers

  const renderPageBackground = (index: number) => (
    <>
      {backgroundLayers?.gradientCss ? (
        <div
          key={`bg-gradient-${index}`}
          className="pointer-events-none absolute inset-0 z-[1]"
          style={{ background: backgroundLayers.gradientCss }}
          aria-hidden
        />
      ) : null}
      {backgroundLayers?.fillImageStyle ? (
        <div
          key={`bg-image-${index}`}
          className="pointer-events-none absolute inset-0 z-[1]"
          style={backgroundLayers.fillImageStyle}
          aria-hidden
        />
      ) : null}
      {backgroundLayers?.watermarkStyle ? (
        <div
          key={`bg-watermark-${index}`}
          className="pointer-events-none absolute inset-0 z-[2] flex items-center justify-center overflow-hidden"
          aria-hidden
        >
          {backgroundLayers.watermarkStyle.imageSrc ? (
            <img
              src={backgroundLayers.watermarkStyle.imageSrc}
              alt=""
              className="max-h-[70%] max-w-[70%] select-none object-contain"
              style={{
                opacity: backgroundLayers.watermarkStyle.opacity,
                transform: `rotate(${backgroundLayers.watermarkStyle.rotationDeg}deg)`,
              }}
            />
          ) : (
            <span
              className="select-none whitespace-nowrap text-[72px] font-light leading-none"
              style={{
                color: backgroundLayers.watermarkStyle.color,
                opacity: backgroundLayers.watermarkStyle.opacity,
                transform: `rotate(${backgroundLayers.watermarkStyle.rotationDeg}deg)`,
              }}
            >
              {backgroundLayers.watermarkStyle.text}
            </span>
          )}
        </div>
      ) : null}
    </>
  )

  return (
    <div
      ref={canvasRef}
      className="ultidrive-docs-canvas min-h-0 flex-1 overflow-auto bg-[#f9fbfd] dark:bg-[#202124]"
    >
      <div
        className={cn("mx-auto", narrowViewport ? "pb-8 pt-0" : "py-8")}
        style={{
          width: scaledWidth,
          minHeight: scaledHeight + verticalPadding,
        }}
      >
        <div
          className="relative mx-auto"
          style={{
            width: scaledWidth,
            height: scaledHeight,
          }}
        >
          <div
            className="absolute left-1/2 top-0 origin-top -translate-x-1/2"
            style={{
              width: pageWidth,
              height: stackHeight,
              transform: `scale(${scale})`,
            }}
          >
            {Array.from({ length: pageCount }, (_, index) => (
              <div
                key={index}
                className={cn(
                  "ultidrive-docs-page absolute left-0 overflow-hidden dark:bg-white",
                  sheetBorderCss && "ultidrive-docs-page--imported-border"
                )}
                style={{
                  top: index * (pageHeight + PAGE_GAP_PX),
                  width: pageWidth,
                  height: pageHeight,
                  backgroundColor: pageBackground,
                  boxShadow:
                    "0 1px 3px 1px rgba(60,64,67,.15), 0 1px 2px 0 rgba(60,64,67,.3)",
                  ...(sheetBorderCss
                    ? {
                        borderTop: sheetBorderCss.top ?? "none",
                        borderRight: sheetBorderCss.right ?? "none",
                        borderBottom: sheetBorderCss.bottom ?? "none",
                        borderLeft: sheetBorderCss.left ?? "none",
                      }
                    : {}),
                }}
                aria-hidden
              >
                {renderPageBackground(index)}
              </div>
            ))}

            {textAreaBorderCss
              ? Array.from({ length: pageCount }, (_, index) => (
                  <div
                    key={`text-border-${index}`}
                    className="pointer-events-none absolute z-[5] box-border"
                    style={{
                      top: index * (pageHeight + PAGE_GAP_PX) + margins.top,
                      left: margins.left,
                      width: pageWidth - margins.left - margins.right,
                      height: pageHeight - margins.top - margins.bottom,
                      borderTop: textAreaBorderCss.top ?? "none",
                      borderRight: textAreaBorderCss.right ?? "none",
                      borderBottom: textAreaBorderCss.bottom ?? "none",
                      borderLeft: textAreaBorderCss.left ?? "none",
                    }}
                    aria-hidden
                  />
                ))
              : null}

            <div
              ref={contentRef}
              className="ultidrive-docs-editor-surface relative z-10"
              style={{
                padding: `${margins.top}px ${margins.right}px ${margins.bottom}px ${margins.left}px`,
                minHeight: stackHeight,
                ["--docs-prose-min-height" as string]: `${innerMinHeight}px`,
              }}
              onMouseDown={(event) => {
                if (!editable) return
                const target = event.target as HTMLElement
                if (target.closest(".ProseMirror")) return
                event.preventDefault()
                focusEditorAtPointer(editor, event.clientX, event.clientY)
              }}
            >
              <EditorContent
                editor={editor}
                className={cn(!editable && "pointer-events-none select-text")}
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

export const DocsPageView = memo(DocsPageViewInner)

export function DocsStatusBar({
  pageLayout,
  pageCount,
  className,
}: {
  pageLayout: DocPageLayout
  pageCount: number
  className?: string
}) {
  return (
    <div
      className={cn(
        "flex shrink-0 items-center justify-between border-t border-[#dadce0] bg-[#edf2fa] px-4 py-1 text-xs text-[#5f6368] dark:border-border dark:bg-muted/40 dark:text-muted-foreground",
        className
      )}
    >
      <span>Page 1 sur {pageCount}</span>
      <span>
        {pageLayout.format.label} ({pageLayout.format.widthMm} × {pageLayout.format.heightMm} mm)
      </span>
    </div>
  )
}
