import { useState, useRef, useCallback, useEffect, useId } from 'react'
import { createPortal } from 'react-dom'

interface Props {
  text: string
  children: React.ReactNode
  delay?: number
}

type TipPos = { top: number; left: number; arrowDir: 'down' | 'up' }

export default function Tooltip({ text, children, delay = 400 }: Props) {
  const [visible, setVisible] = useState(false)
  const [pos, setPos] = useState<TipPos>({ top: 0, left: 0, arrowDir: 'down' })
  const ref = useRef<HTMLDivElement>(null)
  const tipRef = useRef<HTMLDivElement>(null)
  const timer = useRef<ReturnType<typeof setTimeout> | null>(null)
  const tipId = useId()

  const show = useCallback(() => {
    timer.current = setTimeout(() => {
      if (!ref.current) return
      const rect = ref.current.getBoundingClientRect()
      const tipW = 200
      const tipH = 32

      let top = rect.top - tipH - 8
      let left = rect.left + rect.width / 2
      let arrowDir: 'down' | 'up' = 'down'

      if (top < 8) {
        top = rect.bottom + 8
        arrowDir = 'up'
      }

      if (left - tipW / 2 < 8) left = tipW / 2 + 8
      if (left + tipW / 2 > window.innerWidth - 8) left = window.innerWidth - tipW / 2 - 8

      setPos({ top, left, arrowDir })
      setVisible(true)
    }, delay)
  }, [delay])

  const hide = useCallback(() => {
    if (timer.current) { clearTimeout(timer.current); timer.current = null }
    setVisible(false)
  }, [])

  useEffect(() => {
    if (!visible) return
    const onKey = (e: KeyboardEvent) => { if (e.key === 'Escape') hide() }
    document.addEventListener('keydown', onKey)
    return () => document.removeEventListener('keydown', onKey)
  }, [visible, hide])

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

  if (!text) return <>{children}</>

  return (
    <div
      ref={ref}
      onMouseEnter={show}
      onMouseLeave={hide}
      onFocus={show}
      onBlur={hide}
      aria-describedby={visible ? tipId : undefined}
      className="cv-tooltip-wrap"
    >
      {children}
      {visible && createPortal(
        <div
          ref={tipRef}
          id={tipId}
          role="tooltip"
          className={`cv-tooltip cv-tooltip-${pos.arrowDir}`}
          style={{ top: pos.top, left: pos.left }}
          onMouseEnter={() => { if (timer.current) clearTimeout(timer.current) }}
          onMouseLeave={hide}
        >
          {text}
        </div>,
        document.body,
      )}
    </div>
  )
}
