import { useCallback, useEffect, useRef, useState } from 'react'

// Constants for better maintainability
const POPOVER_CLOSE_DELAY = 1500
const FORCE_CLOSE_COOLDOWN = 500
const HOVER_OPEN_DELAY = 300

export const useHoverAndTouchSidebar = (
  sidebarRef: React.RefObject<HTMLElement | null>,
) => {
  const [hovered, setHovered] = useState(false)
  const [isUseable, setIsUseable] = useState(false)
  const isUseableTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined)
  const mouseLeaveTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined)
  const forceCloseTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined)
  const hoverOpenTimeoutRef = useRef<ReturnType<typeof setTimeout>>(undefined)
  const isInForceCloseCooldown = useRef(false)

  const closeSidebar = useCallback((force = false) => {
    // Clear any pending timeouts when explicitly closing
    if (force || mouseLeaveTimeoutRef.current) {
      if (mouseLeaveTimeoutRef.current) {
        clearTimeout(mouseLeaveTimeoutRef.current)
        mouseLeaveTimeoutRef.current = undefined
      }
    }

    // Clear any pending hover open timeout
    if (hoverOpenTimeoutRef.current) {
      clearTimeout(hoverOpenTimeoutRef.current)
      hoverOpenTimeoutRef.current = undefined
    }

    // If this is a forced close (e.g., from user selection), add a cooldown period
    if (force) {
      isInForceCloseCooldown.current = true
      forceCloseTimeoutRef.current = setTimeout(() => {
        isInForceCloseCooldown.current = false
      }, FORCE_CLOSE_COOLDOWN)
    }

    setHovered(false)
  }, [])

  const handleMouseEnter = useCallback(() => {
    // Don't reopen immediately if we're in a force close cooldown period
    if (isInForceCloseCooldown.current) {
      return
    }

    // Clear any pending mouse leave timeout
    if (mouseLeaveTimeoutRef.current) {
      clearTimeout(mouseLeaveTimeoutRef.current)
      mouseLeaveTimeoutRef.current = undefined
    }

    // Clear any existing hover open timeout to prevent multiple pending delays
    if (hoverOpenTimeoutRef.current) {
      clearTimeout(hoverOpenTimeoutRef.current)
      hoverOpenTimeoutRef.current = undefined
    }

    // Delay opening the sidebar by 300ms
    hoverOpenTimeoutRef.current = setTimeout(() => {
      setHovered(true)
      setIsUseable(true)
      hoverOpenTimeoutRef.current = undefined
    }, HOVER_OPEN_DELAY)
  }, [])

  const handleMouseLeave = useCallback(
    (event: MouseEvent) => {
      // Check if we're leaving to enter a popover/dropdown
      const target = event.relatedTarget as Element | null

      // Check if any popovers are currently open
      const hasOpenPopover = document.querySelector(
        '[data-testid="popover-floating"]:not([style*="display: none"])',
      )

      if (target) {
        // Check if the target is a popover or dropdown element
        const isPopoverElement =
          target.closest('[data-testid="popover-floating"]') ||
          target.closest('[data-placement]') ||
          target.closest('.tippy-box') ||
          target.closest('[role="dialog"]')

        if (isPopoverElement || hasOpenPopover) {
          // Don't close immediately if there's an open popover
          mouseLeaveTimeoutRef.current = setTimeout(() => {
            // Double-check if popover is still open before closing
            const stillHasOpenPopover = document.querySelector(
              '[data-testid="popover-floating"]:not([style*="display: none"])',
            )
            if (!stillHasOpenPopover) {
              closeSidebar()
            }
          }, POPOVER_CLOSE_DELAY)
          return
        }
      }

      // If there's an open popover, delay closing
      if (hasOpenPopover) {
        mouseLeaveTimeoutRef.current = setTimeout(() => {
          const stillHasOpenPopover = document.querySelector(
            '[data-testid="popover-floating"]:not([style*="display: none"])',
          )
          if (!stillHasOpenPopover) {
            closeSidebar()
          }
        }, POPOVER_CLOSE_DELAY)
        return
      }

      // Normal mouse leave behavior
      closeSidebar()
    },
    [closeSidebar],
  )

  useEffect(() => {
    const handleTouchEndOutside = (event: TouchEvent) => {
      const sidebarElement = sidebarRef.current
      if (sidebarElement && !sidebarElement.contains(event.target as Node)) {
        closeSidebar()
      }
    }

    const handleTouchStart = () => {
      if (!hovered) {
        setIsUseable(false)
        setHovered(true)
        isUseableTimeoutRef.current = setTimeout(() => {
          setIsUseable(true)
        }, 200)
      }
      document.addEventListener('touchend', handleTouchEndOutside)
    }

    const sidebarElement = sidebarRef.current
    if (sidebarElement) {
      sidebarElement.addEventListener('mouseenter', handleMouseEnter)
      sidebarElement.addEventListener('mouseleave', handleMouseLeave)
      sidebarElement.addEventListener('touchstart', handleTouchStart, {
        passive: true,
      })

      return () => {
        sidebarElement.removeEventListener('mouseenter', handleMouseEnter)
        sidebarElement.removeEventListener('mouseleave', handleMouseLeave)
        sidebarElement.removeEventListener('touchstart', handleTouchStart)
      }
    }
  }, [handleMouseEnter, handleMouseLeave, hovered, closeSidebar, sidebarRef])

  useEffect(() => {
    return () => {
      if (isUseableTimeoutRef.current) {
        clearTimeout(isUseableTimeoutRef.current)
      }
      if (mouseLeaveTimeoutRef.current) {
        clearTimeout(mouseLeaveTimeoutRef.current)
      }
      if (forceCloseTimeoutRef.current) {
        clearTimeout(forceCloseTimeoutRef.current)
      }
      if (hoverOpenTimeoutRef.current) {
        clearTimeout(hoverOpenTimeoutRef.current)
      }
    }
  }, [])

  return [
    hovered,
    isUseable,
    closeSidebar as (force?: boolean) => void,
    setHovered,
  ] as const
}
