"use client"

import { useCallback, useEffect, useRef, useState } from "react"
import { ChevronDown } from "lucide-react"
import type { Editor } from "@tiptap/react"
import type { DocPageLayout, DocPageSetup } from "@/lib/drive/doc-page-setup"
import { pxToMm } from "@/lib/drive/doc-page-setup"
import {
  DOCS_HF_CHROME_BAR_PX,
  defaultFooterZoneHeightPx,
  defaultHeaderZoneHeightPx,
  pageFooterGeometry,
  pageHeaderGeometry,
  resolveRegionForPage,
  toggleDifferentFirstPage,
  type DocsHeaderFooterRegion,
} from "@/lib/drive/docs-header-footer-layout"
import { DocsRegionEditor } from "@/components/drive/richtext/docs-region-editor"
import {
  DocsHeaderFooterFormatDialog,
  DocsPageNumbersDialog,
} from "@/components/drive/richtext/docs-header-footer-dialogs"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { Checkbox } from "@/components/ui/checkbox"
import { Button } from "@/components/ui/button"
import { cn } from "@/lib/utils"

export function extractRegionPlainText(content: Record<string, unknown> | undefined): string {
  if (!content) return ""
  const parts: string[] = []
  const walk = (node: unknown) => {
    if (!node || typeof node !== "object") return
    const record = node as Record<string, unknown>
    if (typeof record.text === "string") parts.push(record.text)
    if (Array.isArray(record.content)) record.content.forEach(walk)
  }
  walk(content)
  return parts.join(" ").trim()
}

export type { DocsHeaderFooterRegion }

export type DocsHeaderFooterEditTarget = {
  region: DocsHeaderFooterRegion
  pageIndex: number
} | null

function DocsHeaderFooterChrome({
  label,
  pageWidth,
  barTop,
  placement,
  showFirstPageCheckbox,
  differentFirstPage,
  onDifferentFirstPageChange,
  onFormatOpen,
  onPageNumOpen,
  onRemove,
}: {
  label: string
  pageWidth: number
  barTop: number
  placement: DocsHeaderFooterRegion
  showFirstPageCheckbox: boolean
  differentFirstPage: boolean
  onDifferentFirstPageChange: (checked: boolean) => void
  onFormatOpen: () => void
  onPageNumOpen: () => void
  onRemove: () => void
}) {
  return (
    <div
      className={cn(
        "docs-hf-chrome pointer-events-none absolute",
        placement === "footer" && "docs-hf-chrome--footer"
      )}
      style={{ top: barTop, left: 0, width: pageWidth, height: DOCS_HF_CHROME_BAR_PX }}
    >
      <div
        className={cn(
          "docs-hf-chrome__bar pointer-events-auto flex h-full items-center justify-between bg-[#f1f3f4] px-4",
          placement === "header" ? "border-t border-[#dadce0]" : "border-b border-[#dadce0]"
        )}
        onMouseDown={(event) => event.preventDefault()}
      >
        <span className="docs-hf-chrome__label">{label}</span>
        <div className="flex items-center gap-4">
          {showFirstPageCheckbox ? (
            <label className="docs-hf-chrome__checkbox-label flex cursor-pointer items-center gap-2">
              <Checkbox
                checked={differentFirstPage}
                onCheckedChange={(v) => onDifferentFirstPageChange(v === true)}
                className="docs-hf-chrome__checkbox"
              />
              Première page différente
            </label>
          ) : null}
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button
                type="button"
                variant="ghost"
                size="sm"
                className="docs-hf-chrome__options h-7 gap-1 px-1.5 hover:bg-transparent dark:hover:bg-transparent"
              >
                Options
                <ChevronDown className="size-3.5" />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem onClick={onFormatOpen}>
                {label === "En-tête"
                  ? "Format de l'en-tête"
                  : "Format du pied de page"}
              </DropdownMenuItem>
              <DropdownMenuItem onClick={onPageNumOpen}>
                Numéros de page
              </DropdownMenuItem>
              <DropdownMenuItem onClick={onRemove}>
                {label === "En-tête"
                  ? "Supprimer l'en-tête"
                  : "Supprimer le pied de page"}
              </DropdownMenuItem>
            </DropdownMenuContent>
          </DropdownMenu>
        </div>
      </div>
    </div>
  )
}

export function DocsHeaderFooterBand({
  region,
  pageLayout,
  pageIndex,
  pageTop,
  pageWidth,
  pageHeight,
  margins,
  editable,
  editingTarget,
  onStartEdit,
  onStopEdit,
  onContentChange,
  onPageSetupChange,
  onRegionEditorReady,
  onRegionHeightMeasure,
}: {
  region: DocsHeaderFooterRegion
  pageLayout: DocPageLayout
  pageIndex: number
  pageTop: number
  pageWidth: number
  pageHeight: number
  margins: { top: number; right: number; bottom: number; left: number }
  editable: boolean
  editingTarget: DocsHeaderFooterEditTarget
  onStartEdit: (region: DocsHeaderFooterRegion, pageIndex: number) => void
  onStopEdit: () => void
  onContentChange: (
    region: DocsHeaderFooterRegion,
    content: Record<string, unknown>,
    meta: { pageIndex: number; contentHeightPx: number },
    options?: { immediate?: boolean }
  ) => void
  onPageSetupChange: (patch: Partial<DocPageSetup>) => void
  onRegionEditorReady?: (editor: Editor | null) => void
  onRegionHeightMeasure?: (payload: {
    region: DocsHeaderFooterRegion
    pageIndex: number
    heightPx: number
  }) => void
}) {
  const isHeader = region === "header"
  const isEditing =
    editingTarget?.region === region && editingTarget.pageIndex === pageIndex
  const canEdit = editable

  const regionData = resolveRegionForPage(pageLayout, region, pageIndex)
  const differentFirstPage = pageLayout.headerFooterDifferentFirstPage ?? false

  const headerGeom = pageHeaderGeometry(pageLayout, pageTop, pageIndex)
  const footerGeom = pageFooterGeometry(pageLayout, pageTop, pageHeight, pageIndex)

  const bandLeft = margins.left
  const bandWidth = pageWidth - margins.left - margins.right

  const zoneHeight = isHeader ? headerGeom.zoneHeight : footerGeom.zoneHeight
  const minZoneHeight = isHeader
    ? defaultHeaderZoneHeightPx(pageLayout)
    : defaultFooterZoneHeightPx(pageLayout)

  const [liveHeight, setLiveHeight] = useState(zoneHeight)
  const liveHeightRef = useRef(zoneHeight)
  liveHeightRef.current = liveHeight

  useEffect(() => {
    if (isEditing) return
    setLiveHeight((height) => Math.min(height, zoneHeight))
  }, [isEditing, zoneHeight])

  /** View: content-sized. Edit: at least default header/footer margin band. */
  const contentHeight = isEditing
    ? Math.max(minZoneHeight, liveHeight)
    : Math.max(20, liveHeight)

  const zoneTop = isHeader
    ? headerGeom.zoneTop
    : footerGeom.zoneBottom - contentHeight

  const headerChromeTop = headerGeom.zoneTop + contentHeight
  const footerChromeTop =
    footerGeom.zoneBottom - contentHeight - DOCS_HF_CHROME_BAR_PX
  const chromeBarTop = isHeader ? headerChromeTop : footerChromeTop

  const [formatOpen, setFormatOpen] = useState(false)
  const [pageNumOpen, setPageNumOpen] = useState(false)
  const contentPersistTimer = useRef<ReturnType<typeof setTimeout> | null>(null)
  const latestContentRef = useRef<Record<string, unknown> | null>(null)

  const persistRegionContent = useCallback(
    (content: Record<string, unknown>, immediate = false) => {
      latestContentRef.current = content
      onContentChange(
        region,
        content,
        {
          pageIndex,
          contentHeightPx: Math.max(minZoneHeight, liveHeightRef.current),
        },
        immediate ? { immediate: true } : undefined
      )
    },
    [minZoneHeight, onContentChange, pageIndex, region]
  )

  const scheduleRegionContentPersist = useCallback(
    (content: Record<string, unknown>) => {
      latestContentRef.current = content
      if (contentPersistTimer.current) clearTimeout(contentPersistTimer.current)
      contentPersistTimer.current = setTimeout(() => {
        persistRegionContent(content)
      }, 800)
    },
    [persistRegionContent]
  )

  const pageNumber =
    pageLayout.pageNumbers?.enabled &&
    pageLayout.pageNumbers.placement === region &&
    (pageLayout.pageNumbers.showOnFirstPage || pageIndex > 0)
      ? (pageLayout.pageNumbers.startAt ?? 1) + pageIndex
      : null

  const handleRemove = useCallback(() => {
    onContentChange(
      region,
      { type: "doc", content: [{ type: "paragraph" }] },
      { pageIndex, contentHeightPx: minZoneHeight },
      { immediate: true }
    )
    onPageSetupChange(isHeader ? { header: null, headerFirstPage: null } : { footer: null, footerFirstPage: null })
    onStopEdit()
  }, [isHeader, minZoneHeight, onContentChange, onPageSetupChange, onStopEdit, pageIndex, region])

  const setupPatch: DocPageSetup = {
    widthMm: pageLayout.format.widthMm,
    heightMm: pageLayout.format.heightMm,
    marginsMm: {
      top: pxToMm(pageLayout.marginsPx.top),
      right: pxToMm(pageLayout.marginsPx.right),
      bottom: pxToMm(pageLayout.marginsPx.bottom),
      left: pxToMm(pageLayout.marginsPx.left),
    },
    headerMarginMm: pageLayout.headerMarginMm,
    footerMarginMm: pageLayout.footerMarginMm,
    headerFooterDifferentFirstPage: differentFirstPage,
    headerFooterDifferentOddEven: pageLayout.headerFooterDifferentOddEven,
    pageNumbers: pageLayout.pageNumbers,
    header: pageLayout.header,
    footer: pageLayout.footer,
    headerFirstPage: pageLayout.headerFirstPage,
    footerFirstPage: pageLayout.footerFirstPage,
  }

  const hasContent =
    regionData?.content && extractRegionPlainText(regionData.content).length > 0

  const regionLabel = isHeader ? "En-tête" : "Pied de page"

  const handleDoubleClick = (event: React.MouseEvent) => {
    if (!canEdit) return
    event.preventDefault()
    event.stopPropagation()
    onStartEdit(region, pageIndex)
  }

  const persistHeight = useCallback(
    (heightPx: number) => {
      const measured = Math.max(20, heightPx)
      setLiveHeight(measured)
      onRegionHeightMeasure?.({ region, pageIndex, heightPx: measured })
    },
    [onRegionHeightMeasure, pageIndex, region]
  )

  useEffect(() => {
    return () => {
      if (contentPersistTimer.current) clearTimeout(contentPersistTimer.current)
    }
  }, [])

  const wasEditingRef = useRef(false)
  useEffect(() => {
    if (wasEditingRef.current && !isEditing) {
      if (contentPersistTimer.current) {
        clearTimeout(contentPersistTimer.current)
        contentPersistTimer.current = null
      }
      persistRegionContent(
        (latestContentRef.current ??
          regionData?.content ??
          ({ type: "doc", content: [{ type: "paragraph" }] } as Record<string, unknown>)),
        true
      )
    }
    wasEditingRef.current = isEditing
  }, [isEditing, persistRegionContent, regionData?.content])

  return (
    <>
      {isEditing ? (
        <>
          <div
            className="docs-hf-editing-backdrop pointer-events-none absolute"
            style={{
              top: zoneTop,
              left: 0,
              width: pageWidth,
              height: contentHeight,
              backgroundColor: pageLayout.pageColor,
            }}
            aria-hidden
          />

          {isHeader ? (
            <div
              className="docs-hf-separator pointer-events-none absolute border-t border-[#dadce0]"
              style={{ top: headerGeom.zoneTop, left: 0, width: pageWidth }}
              aria-hidden
            />
          ) : (
            <div
              className="docs-hf-separator pointer-events-none absolute border-b border-[#dadce0]"
              style={{ top: footerGeom.zoneBottom, left: 0, width: pageWidth }}
              aria-hidden
            />
          )}

          <DocsHeaderFooterChrome
            label={regionLabel}
            pageWidth={pageWidth}
            barTop={chromeBarTop}
            placement={region}
            showFirstPageCheckbox={pageIndex === 0}
            differentFirstPage={differentFirstPage}
            onDifferentFirstPageChange={(checked) => {
              onPageSetupChange(toggleDifferentFirstPage(setupPatch, checked))
            }}
            onFormatOpen={() => setFormatOpen(true)}
            onPageNumOpen={() => setPageNumOpen(true)}
            onRemove={handleRemove}
          />
        </>
      ) : null}

      {!isEditing && !hasContent && canEdit ? (
        <div
          className="docs-hf-hit-area absolute cursor-text"
          style={{
            top: isHeader ? headerGeom.zoneTop : footerGeom.zoneBottom - minZoneHeight,
            left: bandLeft,
            width: bandWidth,
            height: minZoneHeight,
          }}
          onDoubleClick={handleDoubleClick}
          aria-hidden
        />
      ) : null}

      {isEditing || hasContent ? (
        <div
          className={cn(
            "docs-hf-band absolute",
            isHeader ? "docs-hf-band--header" : "docs-hf-band--footer",
            isEditing && "docs-hf-band--editing"
          )}
          style={{
            top: zoneTop,
            left: bandLeft,
            width: bandWidth,
            height: contentHeight,
            ...(isEditing
              ? {
                  backgroundColor: pageLayout.pageColor,
                  "--docs-hf-page-color": pageLayout.pageColor,
                }
              : {}),
          }}
          onDoubleClick={handleDoubleClick}
        >
          <DocsRegionEditor
            content={regionData?.content}
            editable={isEditing}
            autoFocus={isEditing}
            placeholder={regionLabel}
            minHeightPx={isEditing ? minZoneHeight : undefined}
            onUpdate={isEditing ? scheduleRegionContentPersist : undefined}
            onBlur={
              isEditing
                ? () => {
                    requestAnimationFrame(() => {
                      const active = document.activeElement
                      if (
                        active?.closest(".docs-hf-chrome") ||
                        active?.closest('[role="dialog"]') ||
                        active?.closest("[data-radix-popper-content-wrapper]")
                      ) {
                        return
                      }
                      onStopEdit()
                    })
                  }
                : undefined
            }
            onEditorReady={isEditing ? onRegionEditorReady : undefined}
            onContentHeightChange={persistHeight}
          />

          {pageNumber != null && !isEditing ? (
            <div
              className={cn(
                "pointer-events-none absolute text-[11px] text-[#5f6368]",
                pageLayout.pageNumbers?.align === "center"
                  ? "left-1/2 -translate-x-1/2"
                  : pageLayout.pageNumbers?.align === "left"
                    ? "left-0"
                    : "right-0",
                isHeader ? "top-0" : "bottom-0"
              )}
            >
              {pageNumber}
            </div>
          ) : null}
        </div>
      ) : null}

      {isEditing ? (
        <>
          <DocsHeaderFooterFormatDialog
            open={formatOpen}
            onOpenChange={setFormatOpen}
            pageSetup={setupPatch}
            onApply={onPageSetupChange}
          />
          <DocsPageNumbersDialog
            open={pageNumOpen}
            onOpenChange={setPageNumOpen}
            settings={pageLayout.pageNumbers}
            onApply={(pageNumbers) => onPageSetupChange({ pageNumbers })}
          />
        </>
      ) : null}
    </>
  )
}
