"use client"

import { memo, useRef, type ReactNode } from "react"
import { createPortal } from "react-dom"
import { cn } from "@/lib/utils"

export type DocsRulerDragTooltipState = {
  label: string
  x: number
  y: number
} | null

export const DocsRulerMarginDragTooltip = memo(function DocsRulerMarginDragTooltip({
  tooltip,
}: {
  tooltip: DocsRulerDragTooltipState
}) {
  if (!tooltip || typeof document === "undefined") return null

  return createPortal(
    <div
      className="docs-ruler-margin-tooltip pointer-events-none fixed z-[200] rounded px-2 py-1 text-xs font-medium tabular-nums text-white shadow-md"
      style={{
        left: tooltip.x + 12,
        top: tooltip.y + 12,
      }}
      role="status"
      aria-live="polite"
    >
      {tooltip.label}
    </div>,
    document.body
  )
})

/** Blue downward triangle (margin / left indent). */
export const DocsRulerTriangleMarker = memo(function DocsRulerTriangleMarker({
  left,
  className,
}: {
  left: number
  className?: string
}) {
  return (
    <div className={className} style={{ left }} aria-hidden>
      <svg width="8" height="6" viewBox="0 0 8 6" className="block">
        <path d="M0 0 L8 0 L4 6 Z" fill="#1a73e8" />
      </svg>
    </div>
  )
})

/** Blue rectangle on horizontal ruler (first-line indent). */
export const DocsRulerFirstLineMarker = memo(function DocsRulerFirstLineMarker({
  left,
}: {
  left: number
}) {
  return (
    <div
      className="pointer-events-none absolute top-0 h-[5px] w-[6px] -translate-x-1/2 rounded-[1px] bg-[#1a73e8]"
      style={{ left }}
      aria-hidden
    />
  )
})

/** Blue upward triangle on vertical ruler (top margin). */
export const DocsRulerUpTriangleMarker = memo(function DocsRulerUpTriangleMarker({
  top,
}: {
  top: number
}) {
  return (
    <div
      className="pointer-events-none absolute left-1/2 -translate-x-1/2"
      style={{ top }}
      aria-hidden
    >
      <svg width="6" height="8" viewBox="0 0 6 8" className="block">
        <path d="M0 8 L6 8 L3 0 Z" fill="#1a73e8" />
      </svg>
    </div>
  )
})

/** Blue downward triangle on vertical ruler (bottom margin). */
export const DocsRulerDownTriangleMarker = memo(function DocsRulerDownTriangleMarker({
  top,
}: {
  top: number
}) {
  return (
    <div
      className="absolute left-1/2 -translate-x-1/2 -translate-y-full"
      style={{ top }}
      aria-hidden
    >
      <svg width="6" height="8" viewBox="0 0 6 8" className="block">
        <path d="M0 0 L6 0 L3 8 Z" fill="#1a73e8" />
      </svg>
    </div>
  )
})

export const DocsRulerDraggableHandle = memo(function DocsRulerDraggableHandle({
  style,
  className,
  disabled,
  axis,
  ariaLabel,
  onPointerDown,
  children,
}: {
  style: React.CSSProperties
  className?: string
  disabled?: boolean
  axis: "horizontal" | "vertical"
  ariaLabel: string
  onPointerDown: (event: React.PointerEvent<HTMLDivElement>) => void
  children: ReactNode
}) {
  return (
    <div
      role="slider"
      aria-label={ariaLabel}
      aria-disabled={disabled || undefined}
      className={cn(
        "docs-ruler-drag-handle absolute touch-none select-none",
        axis === "horizontal"
          ? "bottom-0 -translate-x-1/2 cursor-ew-resize"
          : "left-1/2 -translate-x-1/2 cursor-ns-resize",
        disabled ? "pointer-events-none" : "pointer-events-auto",
        className
      )}
      style={style}
      onPointerDown={disabled ? undefined : onPointerDown}
    >
      <div
        className={cn(
          "flex items-center justify-center",
          axis === "horizontal" ? "h-5 w-4 -mb-0.5" : "h-4 w-5"
        )}
      >
        {children}
      </div>
    </div>
  )
})

export function useRulerPointerDrag({
  rulerRef,
  axis,
  disabled,
  onDrag,
  onDragEnd,
}: {
  rulerRef: React.RefObject<HTMLElement | null>
  axis: "horizontal" | "vertical"
  disabled?: boolean
  onDrag: (pagePx: number, clientX: number, clientY: number) => void
  onDragEnd: () => void
}) {
  const draggingRef = useRef(false)

  const onPointerDown = (event: React.PointerEvent<HTMLDivElement>) => {
    if (disabled) return
    event.preventDefault()
    event.stopPropagation()

    const handle = event.currentTarget
    handle.setPointerCapture(event.pointerId)
    draggingRef.current = true
    document.body.style.userSelect = "none"
    document.body.style.cursor = axis === "horizontal" ? "ew-resize" : "ns-resize"

    const readPagePx = (clientX: number, clientY: number) => {
      const ruler = rulerRef.current
      if (!ruler) return null
      const rect = ruler.getBoundingClientRect()
      const scaleAttr = ruler.dataset.docsRulerScale
      const scale = scaleAttr ? Number.parseFloat(scaleAttr) : 1
      if (!Number.isFinite(scale) || scale <= 0) return null
      return axis === "horizontal"
        ? (clientX - rect.left) / scale
        : (clientY - rect.top) / scale
    }

    const move = (clientX: number, clientY: number) => {
      const pagePx = readPagePx(clientX, clientY)
      if (pagePx != null) onDrag(pagePx, clientX, clientY)
    }

    move(event.clientX, event.clientY)

    const onMove = (ev: PointerEvent) => move(ev.clientX, ev.clientY)
    const onUp = (ev: PointerEvent) => {
      draggingRef.current = false
      document.body.style.userSelect = ""
      document.body.style.cursor = ""
      if (handle.hasPointerCapture(ev.pointerId)) {
        handle.releasePointerCapture(ev.pointerId)
      }
      window.removeEventListener("pointermove", onMove)
      window.removeEventListener("pointerup", onUp)
      window.removeEventListener("pointercancel", onUp)
      onDragEnd()
    }

    window.addEventListener("pointermove", onMove)
    window.addEventListener("pointerup", onUp)
    window.addEventListener("pointercancel", onUp)
  }

  return { onPointerDown, draggingRef }
}
