"use client"
import { useEffect, useMemo, useRef, useState } from "react"
import { Maximize2, Minimize2, X } from "lucide-react"

/**
 * 视觉类节点统一大预览：
 * - **在 ReactFlow 节点 DOM 内**作为 absolute 元素，底边贴当前缩略图上方边缘
 * - 跟随 ReactFlow 画布 pan/zoom 一起变化（属于"无限画布"的一部分）
 * - 默认按原比例 fit 到可视区域，并标注原始分辨率 / 当前缩放比例
 * - pinned 后可切换到 1:1；大图在预览框内滚动查看局部
 * - 不 pinned 时：pointer-events-none，依赖调用方传入 visible
 * - pinned=true：强制 visible，pointer-events 开启，可点 × 关闭
 * - 用法：渲染在节点根层，不要放进 overflow-x-auto 缩略图滚动条里
 */
interface Props {
  imgSrc?: string
  videoSrc?: string
  poster?: string
  aspect?: string
  label?: string
  caption?: string
  borderClass?: string
  visible?: boolean
  anchorX?: number
  anchorY?: number
  pinned?: boolean
  onClose?: () => void
}

export function HoverPreview({
  imgSrc, videoSrc, poster, aspect,
  label, caption,
  borderClass = "border-violet-300/55",
  visible = false,
  anchorX,
  anchorY,
  pinned = false,
  onClose,
}: Props) {
  const shown = pinned || visible
  const imgRef = useRef<HTMLImageElement>(null)
  const videoRef = useRef<HTMLVideoElement>(null)
  const [naturalSize, setNaturalSize] = useState<{ width: number; height: number } | null>(null)
  const [actualSize, setActualSize] = useState(false)
  const [viewport, setViewport] = useState({ width: 1200, height: 800 })

  useEffect(() => {
    setNaturalSize(null)
    setActualSize(false)
  }, [imgSrc, videoSrc])

  useEffect(() => {
    if (!pinned) setActualSize(false)
  }, [pinned])

  useEffect(() => {
    const update = () => setViewport({
      width: window.innerWidth || 1200,
      height: window.innerHeight || 800,
    })
    update()
    window.addEventListener("resize", update)
    return () => window.removeEventListener("resize", update)
  }, [])

  useEffect(() => {
    if (!shown) return
    const raf = window.requestAnimationFrame(() => {
      const img = imgRef.current
      if (img?.complete && img.naturalWidth && img.naturalHeight) {
        setNaturalSize({ width: img.naturalWidth, height: img.naturalHeight })
        return
      }
      const video = videoRef.current
      if (video?.videoWidth && video.videoHeight) {
        setNaturalSize({ width: video.videoWidth, height: video.videoHeight })
      }
    })
    return () => window.cancelAnimationFrame(raf)
  }, [imgSrc, shown, videoSrc])

  const fitScale = useMemo(() => {
    if (!naturalSize) return null
    const maxWidth = Math.min(920, viewport.width * 0.7)
    const maxHeight = Math.min(820, viewport.height * 0.72)
    return Math.min(1, maxWidth / naturalSize.width, maxHeight / naturalSize.height)
  }, [naturalSize, viewport.height, viewport.width])

  const dimensionText = naturalSize ? `${naturalSize.width} × ${naturalSize.height}` : "读取中"
  const scaleText = naturalSize
    ? actualSize ? "1:1 原寸" : `Fit ${Math.round((fitScale ?? 1) * 100)}%`
    : actualSize ? "1:1 原寸" : "Fit"

  const visibilityCls = shown
    ? pinned ? "opacity-100 pointer-events-auto" : "opacity-100 pointer-events-none"
    : "pointer-events-none opacity-0"
  const previewFrameStyle = actualSize
    ? {
        width: "max-content",
        maxWidth: "min(78vw, 1040px)",
        maxHeight: "min(76vh, 860px)",
        overflow: "auto",
      }
    : {
        width: "max-content",
        maxWidth: "min(70vw, 920px)",
        maxHeight: "min(72vh, 820px)",
        overflow: "hidden",
      }
  const mediaStyle = actualSize
    ? { width: "auto", height: "auto", maxWidth: "none", maxHeight: "none" }
    : { width: "auto", height: "auto", maxWidth: "min(70vw, 920px)", maxHeight: "min(72vh, 820px)" }

  return (
    <div
      className={`absolute transition-all duration-150 z-[120] ${visibilityCls}`}
      style={{
        top: typeof anchorY === "number" ? `${anchorY - 8}px` : undefined,
        bottom: typeof anchorY === "number" ? undefined : "calc(100% + 8px)",
        left: typeof anchorX === "number" ? `${anchorX}px` : "50%",
        transform: `${typeof anchorY === "number" ? "translate(-50%, -100%)" : "translateX(-50%)"} scale(${shown ? 1 : 0.96})`,
        transformOrigin: "bottom center",
      }}
    >
      <div className={`relative rounded-lg overflow-hidden border-2 bg-black shadow-2xl ${pinned ? "ring-2 ring-violet-400/70" : ""} ${borderClass}`}
        style={previewFrameStyle}>
        {shown && (
          <div className="absolute left-2 top-2 z-10 overflow-hidden rounded-lg border border-white/25 bg-black/88 text-white shadow-[0_10px_30px_rgba(0,0,0,0.42)] backdrop-blur">
            <div className="border-b border-white/12 bg-white/10 px-2.5 py-1 text-[9.5px] font-semibold leading-none text-white/72">
              原始尺寸
            </div>
            <div className="flex items-baseline gap-2 px-2.5 py-1.5">
              <span className="font-mono text-[15px] font-bold leading-none text-white">
                {dimensionText}
              </span>
              <span className="rounded bg-violet-500/28 px-1.5 py-0.5 text-[10px] font-semibold leading-none text-violet-100">
                {scaleText}
              </span>
            </div>
          </div>
        )}
        {videoSrc ? (
          <video
            ref={videoRef}
            src={videoSrc}
            poster={poster}
            muted
            loop
            playsInline
            autoPlay
            preload="auto"
            className="block"
            style={mediaStyle}
            onLoadedMetadata={(e) => {
              const video = e.currentTarget
              if (video.videoWidth && video.videoHeight) {
                setNaturalSize({ width: video.videoWidth, height: video.videoHeight })
              }
              video.play().catch(() => {})
            }}
            onCanPlay={(e) => { e.currentTarget.play().catch(() => {}) }}
          />
        ) : imgSrc ? (
          <img
            ref={imgRef}
            src={imgSrc}
            alt=""
            className="block"
            style={mediaStyle}
            onLoad={(e) => {
              const img = e.currentTarget
              if (img.naturalWidth && img.naturalHeight) {
                setNaturalSize({ width: img.naturalWidth, height: img.naturalHeight })
              }
            }}
          />
        ) : (
          <div className="w-40 bg-black/40" style={{ aspectRatio: aspect ?? "1/1" }} />
        )}
        {(label || caption) && (
          <div className="px-2 py-1 bg-black/80 text-white text-[11px] flex items-center justify-between">
            {label && <span>{label}</span>}
            {caption && <span className="text-white/60 font-mono">{caption}</span>}
          </div>
        )}
        {pinned && onClose && (
          <div className="absolute right-1 top-1 z-10 flex items-center gap-1">
            <button
              type="button"
              onClick={(e) => { e.stopPropagation(); setActualSize((x) => !x) }}
              onMouseDown={(e) => e.stopPropagation()}
              title={actualSize ? "适应预览" : "1:1 查看"}
              className="inline-flex h-7 w-7 items-center justify-center rounded-full bg-black/75 text-white shadow-lg backdrop-blur hover:bg-violet-500"
            >
              {actualSize ? <Minimize2 className="h-4 w-4" /> : <Maximize2 className="h-4 w-4" />}
            </button>
            <button
              type="button"
              onClick={(e) => { e.stopPropagation(); onClose() }}
              onMouseDown={(e) => e.stopPropagation()}
              title="取消固定预览"
              className="inline-flex h-7 w-7 items-center justify-center rounded-full bg-black/75 text-white shadow-lg backdrop-blur hover:bg-rose-500"
            >
              <X className="h-4 w-4" />
            </button>
          </div>
        )}
      </div>
    </div>
  )
}
