import type { CSSProperties, MouseEvent } from 'react'
import { useState } from 'react'

import isUndefined from 'lodash/isUndefined'

import { useToggle } from './useToggle'

type TooltipParams = {
  anchorId?: string,
  horizontalPosition?: 'left' | 'center' | 'right',
  indent?: number,
  tooltipText: string,
  verticalPosition?: 'top' | 'bottom',
}

export const useTooltip = () => {
  const [stateTooltipStyle, setTooltipStyle] = useState<CSSProperties>({})
  const [stateAnchorId, setAnchorId] = useState<string | null>(null)
  const [stateTooltipText, setTooltipText] = useState('')

  const {
    close: hideTooltip,
    isOpen: isTooltipShown,
    open: showTooltip,
  } = useToggle()

  const onMouseOver = ({
    anchorId,
    horizontalPosition = 'center',
    indent = 10,
    tooltipText,
    verticalPosition = 'bottom',
  }: TooltipParams) => (e: MouseEvent<HTMLElement>) => {
    const target = e.target as HTMLElement

    if (anchorId && target.id !== anchorId) return

    const {
      left,
      right,
      top,
    } = target.getBoundingClientRect()

    const coords: Partial<DOMRect> = {
      top: verticalPosition === 'bottom'
        ? top + target.clientHeight + indent
        : top - target.clientHeight - indent,

      ...(horizontalPosition === 'center' && { left: left + target.clientWidth / 2 }),
      ...(horizontalPosition === 'left' && { left }),
      ...(horizontalPosition === 'right' && { right }),
    }

    const tooltipStyle: CSSProperties = {
      left: !isUndefined(coords.left) ? `${coords.left}px` : 'auto',
      position: 'fixed',
      right: !isUndefined(coords.right) ? `${window.innerWidth - coords.right}px` : 'auto',
      top: `${coords.top}px`,
      zIndex: 999,

      ...(horizontalPosition === 'center' && { transform: 'translateX: (-50%)' }),
      ...(verticalPosition === 'top' && { transform: 'translateY: (-50%)' }),
      ...(horizontalPosition === 'center' && verticalPosition === 'top' && { transform: 'translate: (-50%, -50%)' }),
    }

    if (anchorId) {
      setAnchorId(anchorId)
    }

    setTooltipStyle(tooltipStyle)
    showTooltip()
    setTooltipText(tooltipText)
  }

  const onMouseLeave = () => {
    hideTooltip()
    setAnchorId(null)
    setTooltipStyle({})
  }

  return {
    anchorId: stateAnchorId,
    isTooltipShown,
    onMouseLeave,
    onMouseOver,
    tooltipStyle: stateTooltipStyle,
    tooltipText: stateTooltipText,
  }
}
