import React, {
  useCallback,
  useEffect,
  useRef,
  useState,
  type ComponentProps,
  type ReactNode,
} from 'react';
import { Tooltip as AriaTooltip, TooltipTrigger } from 'react-aria-components';

import { styles } from '../../style';

import { View } from './View';

type TooltipProps = Partial<ComponentProps<typeof AriaTooltip>> & {
  children: ReactNode;
  content: ReactNode;
  triggerProps?: Partial<ComponentProps<typeof TooltipTrigger>>;
};

export const Tooltip = ({
  children,
  content,
  triggerProps = {},
  ...props
}: TooltipProps) => {
  const triggerRef = useRef(null);
  const [isHovered, setIsHover] = useState(false);

  const hoverTimeoutRef = useRef<ReturnType<typeof setTimeout>>();

  const handlePointerEnter = useCallback(() => {
    const timeout = setTimeout(() => {
      setIsHover(true);
    }, triggerProps.delay ?? 300);

    hoverTimeoutRef.current = timeout;
  }, [triggerProps.delay]);

  const handlePointerLeave = useCallback(() => {
    if (hoverTimeoutRef.current) {
      clearTimeout(hoverTimeoutRef.current);
    }

    setIsHover(false);
  }, []);

  // Force closing the tooltip whenever the disablement state changes
  useEffect(() => {
    setIsHover(false);
  }, [triggerProps.isDisabled]);

  return (
    <View
      style={{ minHeight: 'auto' }}
      ref={triggerRef}
      onPointerEnter={handlePointerEnter}
      onPointerLeave={handlePointerLeave}
    >
      <TooltipTrigger
        isOpen={isHovered && !triggerProps.isDisabled}
        {...triggerProps}
      >
        {children}

        <AriaTooltip triggerRef={triggerRef} style={styles.tooltip} {...props}>
          {content}
        </AriaTooltip>
      </TooltipTrigger>
    </View>
  );
};