"use client"

import { type MouseEvent as ReactMouseEvent, type ReactNode, useState } from "react"
import { createPortal } from "react-dom"
import { Film, Loader2, Trash2 } from "lucide-react"

type MediaAssetAction = {
  key: string
  label: string
  icon: ReactNode
  onClick: () => void
  disabled?: boolean
  busy?: boolean
  tone?: "neutral" | "cyan" | "rose"
}

type MediaAssetPreviewPlacement = "auto" | "left" | "right"

type MediaAssetTileProps = {
  kind?: "image" | "video"
  src?: string
  poster?: string
  href?: string
  alt?: string
  title?: string
  label?: ReactNode
  meta?: ReactNode
  previewDetail?: ReactNode
  className?: string
  mediaClassName?: string
  objectFit?: "contain" | "cover"
  previewObjectFit?: "contain" | "cover"
  previewClassName?: string
  previewPlacement?: MediaAssetPreviewPlacement
  previewMaxWidth?: number
  videoControls?: boolean
  selected?: boolean
  disabled?: boolean
  busy?: boolean
  topLeft?: ReactNode
  topRight?: ReactNode
  bottom?: ReactNode
  emptyText?: string
  onClick?: () => void
  onDelete?: () => void
  deleteLabel?: string
  deleting?: boolean
  deleteDisabled?: boolean
  actions?: MediaAssetAction[]
  actionsAlwaysVisible?: boolean
  disablePreview?: boolean
}

const actionToneClass: Record<NonNullable<MediaAssetAction["tone"]>, string> = {
  neutral: "border-white/18 bg-black/78 text-white/82 hover:border-white/42 hover:bg-white/12",
  cyan: "border-cyan-100/35 bg-black/78 text-cyan-100 hover:border-cyan-100/70 hover:bg-cyan-500/25",
  rose: "border-rose-100/35 bg-black/78 text-rose-100 hover:border-rose-100/70 hover:bg-rose-500/25",
}

function mediaObjectClass(fit: "contain" | "cover") {
  return fit === "cover" ? "object-cover" : "object-contain"
}

function previewPosition(event: ReactMouseEvent<HTMLElement>, placement: MediaAssetPreviewPlacement, maxWidth: number) {
  const margin = 16
  const previewWidth = Math.min(maxWidth, window.innerWidth - margin * 2)
  const previewHeight = Math.min(760, window.innerHeight - margin * 2)
  let left = placement === "left" ? event.clientX - previewWidth - 18 : event.clientX + 18
  let top = event.clientY + 18
  if (placement === "auto" && left + previewWidth > window.innerWidth - margin) left = event.clientX - previewWidth - 18
  if (placement === "right" && left + previewWidth > window.innerWidth - margin) left = window.innerWidth - previewWidth - margin
  if (placement === "left" && left < margin) left = margin
  if (top + previewHeight > window.innerHeight - margin) top = window.innerHeight - previewHeight - margin
  return {
    left: Math.max(margin, Math.min(left, window.innerWidth - previewWidth - margin)),
    top: Math.max(margin, top),
    width: previewWidth,
  }
}

export function MediaAssetTile({
  kind = "image",
  src,
  poster,
  href,
  alt = "",
  title,
  label,
  meta,
  previewDetail,
  className = "",
  mediaClassName = "",
  objectFit = "contain",
  previewObjectFit,
  previewClassName = "",
  previewPlacement = "auto",
  previewMaxWidth = 520,
  videoControls = false,
  selected = false,
  disabled = false,
  busy = false,
  topLeft,
  topRight,
  bottom,
  emptyText,
  onClick,
  onDelete,
  deleteLabel = "删除素材",
  deleting = false,
  deleteDisabled = false,
  actions = [],
  actionsAlwaysVisible = false,
  disablePreview = false,
}: MediaAssetTileProps) {
  const [position, setPosition] = useState<{ left: number; top: number; width: number } | null>(null)
  const mediaSrc = src || poster || ""
  const canPreview = !!mediaSrc && !disablePreview
  const fit = mediaObjectClass(objectFit)
  const previewFit = mediaObjectClass(previewObjectFit ?? objectFit)

  const updatePreview = (event: ReactMouseEvent<HTMLElement>) => {
    if (!canPreview) return
    setPosition(previewPosition(event, previewPlacement, previewMaxWidth))
  }

  const media = kind === "video" && src ? (
    <video src={src} poster={poster} muted playsInline controls={videoControls} preload="metadata" className={`h-full w-full ${fit} ${mediaClassName}`} />
  ) : mediaSrc ? (
    <img src={mediaSrc} alt={alt} className={`h-full w-full ${fit} ${mediaClassName}`} />
  ) : (
    <div className="flex h-full w-full items-center justify-center text-white/28">
      <Film className="h-4 w-4" />
      {emptyText ? <span className="ml-1 text-[10px]">{emptyText}</span> : null}
    </div>
  )

  const interactiveClass = disabled ? "cursor-not-allowed opacity-55" : onClick || href ? "cursor-pointer" : ""
  const bodyClass = `absolute inset-0 block h-full w-full overflow-hidden focus:outline-none focus:ring-1 focus:ring-cyan-200/70 ${interactiveClass}`
  const body = href ? (
    <a href={href} target="_blank" rel="noreferrer" className={bodyClass} onClick={(event) => { if (disabled) event.preventDefault() }}>
      {media}
    </a>
  ) : onClick ? (
    <button type="button" disabled={disabled} onClick={onClick} className={bodyClass}>
      {media}
    </button>
  ) : (
    <div className={bodyClass}>{media}</div>
  )

  const preview = position && canPreview && typeof document !== "undefined"
    ? createPortal(
        <div
          className={`pointer-events-none fixed z-[10000] w-[min(520px,calc(100vw-32px))] rounded-xl border border-white/15 bg-black/94 p-3 shadow-[0_28px_80px_rgba(0,0,0,0.72)] ${previewClassName}`}
          style={{ left: position.left, top: position.top, width: position.width }}
        >
          <div className="flex max-h-[min(76vh,720px)] items-center justify-center overflow-hidden rounded-lg bg-black">
            {kind === "video" && src ? (
              <video
                src={src}
                poster={poster}
                muted
                loop
                playsInline
                autoPlay
                preload="auto"
                className={`max-h-[min(74vh,700px)] max-w-full ${previewFit}`}
              />
            ) : (
              <img
                src={mediaSrc}
                alt=""
                className={`max-h-[min(74vh,700px)] max-w-full ${previewFit}`}
              />
            )}
          </div>
          {(label || meta || previewDetail) && (
            <div className="mt-2 text-[11px] leading-snug text-white/66">
              {(label || meta) && (
                <div className="flex items-center justify-between gap-3">
                  <span className="min-w-0 truncate">{label}</span>
                  {meta ? <span className="shrink-0 font-mono text-white/44">{meta}</span> : null}
                </div>
              )}
              {previewDetail ? <div className="mt-1 text-white/58">{previewDetail}</div> : null}
            </div>
          )}
        </div>,
        document.body,
      )
    : null

  return (
    <div
      className={`group relative overflow-hidden rounded border bg-black transition ${selected ? "border-emerald-300/70" : "border-white/10 hover:border-cyan-300/45"} ${className}`}
      title={title}
      onMouseEnter={updatePreview}
      onMouseMove={updatePreview}
      onMouseLeave={() => setPosition(null)}
    >
      {body}
      {preview}
      {topLeft ? <div className="pointer-events-none absolute left-1 top-1 z-10">{topLeft}</div> : null}
      {topRight ? <div className="pointer-events-none absolute right-1 top-1 z-10">{topRight}</div> : null}
      {bottom ? <div className="pointer-events-none absolute bottom-1 left-1 right-1 z-10">{bottom}</div> : null}
      {(actions.length || onDelete) ? (
        <div className={`absolute right-1 top-1 z-20 flex flex-col gap-0.5 transition ${actionsAlwaysVisible ? "opacity-100" : "opacity-0 group-hover:opacity-100 group-focus-within:opacity-100"}`}>
          {actions.map((action) => (
            <button
              key={action.key}
              type="button"
              onClick={(event) => {
                event.preventDefault()
                event.stopPropagation()
                if (!action.disabled && !action.busy) action.onClick()
              }}
              disabled={action.disabled || action.busy}
              className={`inline-flex h-5 w-5 items-center justify-center rounded-full border transition focus:outline-none focus:ring-1 focus:ring-cyan-100/70 disabled:cursor-not-allowed disabled:opacity-60 ${actionToneClass[action.tone ?? "neutral"]}`}
              aria-label={action.label}
              title={action.label}
            >
              {action.busy ? <Loader2 className="h-3 w-3 animate-spin" /> : action.icon}
            </button>
          ))}
          {onDelete ? (
            <button
              type="button"
              onClick={(event) => {
                event.preventDefault()
                event.stopPropagation()
                if (!deleteDisabled && !deleting) onDelete()
              }}
              disabled={deleteDisabled || deleting}
              className="inline-flex h-5 w-5 items-center justify-center rounded-full border border-rose-100/35 bg-black/78 text-rose-100 transition hover:border-rose-100/70 hover:bg-rose-500/25 focus:outline-none focus:ring-1 focus:ring-rose-100/70 disabled:cursor-not-allowed disabled:opacity-60"
              aria-label={deleteLabel}
              title={deleteLabel}
            >
              {deleting ? <Loader2 className="h-3 w-3 animate-spin" /> : <Trash2 className="h-3 w-3" />}
            </button>
          ) : null}
        </div>
      ) : null}
      {busy ? (
        <div className="absolute inset-0 z-30 flex items-center justify-center bg-black/65">
          <Loader2 className="h-4 w-4 animate-spin text-white/80" />
        </div>
      ) : null}
    </div>
  )
}
