"use client"

import { memo, useEffect, useRef, useState } from "react"
import { EditorContent, type Editor } from "@tiptap/react"
import {
  getPageFormat,
  PAGE_MARGIN_PX,
  pageFormatHeightPx,
  pageFormatWidthPx,
  type PageFormatId,
} from "@/lib/drive/page-formats"
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,
  pageFormatId,
  zoom,
  editable,
  onPageCountChange,
}: {
  editor: Editor
  pageFormatId: PageFormatId
  zoom: number
  editable: boolean
  onPageCountChange?: (count: number) => void
}) {
  const format = getPageFormat(pageFormatId)
  const pageWidth = pageFormatWidthPx(format)
  const pageHeight = pageFormatHeightPx(format)
  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 = PAGE_MARGIN_PX * 2 + contentHeight
      const count = Math.max(1, Math.ceil(paddedHeight / pageHeight))
      setPageCount((prev) => {
        if (prev === count) return prev
        onPageCountChangeRef.current?.(count)
        return 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)
    }
  }, [pageHeight, editor])

  const stackHeight = pageCount * pageHeight + (pageCount - 1) * PAGE_GAP_PX
  const proseMinHeight = stackHeight - PAGE_MARGIN_PX * 2
  const scaledHeight = stackHeight * scale
  const verticalPadding = narrowViewport ? 32 : 64

  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="ultidrive-docs-page absolute left-0 bg-white dark:bg-white"
                style={{
                  top: index * (pageHeight + PAGE_GAP_PX),
                  width: pageWidth,
                  height: pageHeight,
                  boxShadow:
                    "0 1px 3px 1px rgba(60,64,67,.15), 0 1px 2px 0 rgba(60,64,67,.3)",
                }}
                aria-hidden
              />
            ))}

            <div
              ref={contentRef}
              className="ultidrive-docs-editor-surface relative z-10"
              style={{
                padding: PAGE_MARGIN_PX,
                minHeight: stackHeight,
                ["--docs-prose-min-height" as string]: `${Math.max(
                  pageHeight - PAGE_MARGIN_PX * 2,
                  proseMinHeight
                )}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({
  pageFormatId,
  pageCount,
  className,
}: {
  pageFormatId: PageFormatId
  pageCount: number
  className?: string
}) {
  const format = getPageFormat(pageFormatId)

  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>
        {format.label} ({format.widthMm} × {format.heightMm} mm)
      </span>
    </div>
  )
}
