import React, {
  useCallback,
  useEffect,
  useLayoutEffect,
  useRef,
  useState,
} from 'react';
import { createPortal } from 'react-dom';

interface InfoTooltipProps {
  /** Help text shown inside the tooltip bubble. */
  text: string;
}

/**
 * Small "?" trigger that opens a help bubble. The bubble is rendered
 * through a React portal directly into ``document.body`` so it cannot be
 * trapped behind sibling cards by an ancestor stacking context — any
 * ancestor with ``transform`` / ``filter`` / ``will-change`` would
 * otherwise contain a ``position: fixed`` child and pin even very high
 * z-index values underneath neighbouring cards.
 *
 * @param {InfoTooltipProps} props - Component props.
 * @returns {JSX.Element} Trigger + portalled tooltip bubble.
 */
const InfoTooltip = ({ text }: InfoTooltipProps): JSX.Element => {
  const [open, setOpen] = useState(false);
  const [coords, setCoords] = useState<{ top: number; left: number } | null>(
    null
  );
  const triggerRef = useRef<HTMLSpanElement>(null);

  const showTooltip = useCallback(() => setOpen(true), []);
  const hideTooltip = useCallback(() => setOpen(false), []);

  useLayoutEffect(() => {
    if (!open || !triggerRef.current) return;
    const triggerRect = triggerRef.current.getBoundingClientRect();
    setCoords({
      top: triggerRect.top - 8,
      left: triggerRect.left + triggerRect.width / 2,
    });
  }, [open]);

  useEffect(() => {
    if (!open) return undefined;
    const closeOnScroll = () => setOpen(false);
    window.addEventListener('scroll', closeOnScroll, true);
    window.addEventListener('resize', closeOnScroll);
    return () => {
      window.removeEventListener('scroll', closeOnScroll, true);
      window.removeEventListener('resize', closeOnScroll);
    };
  }, [open]);

  const tooltipBubble =
    open && coords && typeof document !== 'undefined'
      ? createPortal(
          <span
            role="tooltip"
            style={{
              position: 'fixed',
              top: coords.top,
              left: coords.left,
              transform: 'translate(-50%, -100%)',
              background: '#1a1a1a',
              color: '#fff',
              fontSize: '11px',
              fontWeight: 400,
              lineHeight: 1.4,
              padding: '6px 10px',
              borderRadius: '6px',
              whiteSpace: 'normal',
              width: 'max-content',
              maxWidth: '220px',
              zIndex: 2147483647,
              pointerEvents: 'none',
              boxShadow: '0 4px 12px rgba(0,0,0,0.15)',
            }}
          >
            {text}
          </span>,
          document.body
        )
      : null;

  return (
    <>
      <span
        ref={triggerRef}
        onMouseEnter={showTooltip}
        onMouseLeave={hideTooltip}
        onFocus={showTooltip}
        onBlur={hideTooltip}
        tabIndex={0}
        aria-label={text}
        style={{
          display: 'inline-flex',
          alignItems: 'center',
          justifyContent: 'center',
          width: 14,
          height: 14,
          borderRadius: '50%',
          background: '#e0e0e0',
          color: '#616161',
          fontSize: 9,
          fontWeight: 600,
          lineHeight: 1,
          marginLeft: 4,
          cursor: 'help',
          flexShrink: 0,
        }}
      >
        ?
      </span>
      {tooltipBubble}
    </>
  );
};

export default InfoTooltip;
