import { useDraggable, useDroppable } from '@dnd-kit/core'
import { CSS } from '@dnd-kit/utilities'
import { useRef } from 'react'

import TagLink from '@/components/TagLink'
import { cn } from '@/lib/utils'

import type { CSSProperties, FC, MutableRefObject } from 'react'

import type { Tag } from '@/types'

type Props = {
    tag:              Tag
    nestLevel:        number
    pathKey:          string
    parentTagId?:     number
    suppressClickRef: MutableRefObject<boolean> }


export default (({ tag, nestLevel, pathKey, parentTagId, suppressClickRef }: Props) => {
  const dndId = `tag-node:${ pathKey }`

  const downPosRef = useRef<{ x: number; y: number } | null> (null)
  const armedRef = useRef (false)

  const armEatNextClick = () => {
    if (armedRef.current)
      return

    armedRef.current = true
    suppressClickRef.current = true

    const handler = (ev: MouseEvent) => {
      ev.preventDefault ()
      ev.stopPropagation ()
      armedRef.current = false
      suppressClickRef.current = false
    }

    addEventListener ('click', handler, { capture: true, once: true })
  }

  const { attributes,
	  listeners,
	  setNodeRef: setDragRef,
	  transform,
	  isDragging: dragging } = useDraggable ({ id:    dndId,
						   data:  { kind:   'tag',
							    tagId:  tag.id,
							    parentTagId } })

  const { setNodeRef: setDropRef, isOver: over } = useDroppable ({
      id:   dndId,
      data: { kind: 'tag', tagId: tag.id } })

  const style: CSSProperties = { transform:   CSS.Translate.toString (transform),
				 visibility:  dragging ? 'hidden' : 'visible' }

  return (
      <div
	  onPointerDownCapture={e => {
	    downPosRef.current = { x: e.clientX, y: e.clientY }
	  }}
	  onPointerMoveCapture={e => {
	    const p = downPosRef.current
	    if (!(p))
	      return
	    const dx = e.clientX - p.x
	    const dy = e.clientY - p.y
	    if (dx * dx + dy * dy >= 9)
	      armEatNextClick ()
	  }}
	  onPointerUpCapture={() => {
	    downPosRef.current = null
	  }}
	  onClickCapture={e => {
	    if (suppressClickRef.current)
	      {
		e.preventDefault ()
		e.stopPropagation ()
	      }
	  }}
	  ref={node => {
	    setDragRef (node)
	    setDropRef (node)
	  }}
	  style={style}
	  className={cn ('rounded select-none', over && 'ring-2 ring-offset-2')}
	  {...attributes}
	  {...listeners}>
	<TagLink tag={tag} nestLevel={nestLevel}/>
      </div>)
}) satisfies FC<Props>
