import React, { ReactNode, useEffect, useRef, useState } from 'react';
import ReactDOM from 'react-dom';
import styled, { keyframes } from 'styled-components';
import { uiColors } from '../../constants/uiColors';
import { RPGUIRoot } from '../RPGUI/RPGUIRoot';

interface TooltipProps {
  content: string | ReactNode;
  direction?: 'top' | 'bottom' | 'left' | 'right';
  backgroundColor?: string;
  textColor?: string;
  children: ReactNode;
  showDelay?: number;
  hideDelay?: number;
}

export const SimpleTooltip: React.FC<TooltipProps> = ({
  content,
  direction = 'top',
  backgroundColor = uiColors.raisinBlack,
  textColor = uiColors.white,
  children,
  showDelay = 200,
  hideDelay = 200,
}) => {
  const [visible, setVisible] = useState(false);
  const [tooltipPosition, setTooltipPosition] = useState({ top: 0, left: 0 });
  const tooltipRef = useRef<HTMLDivElement>(null);
  const triggerRef = useRef<HTMLDivElement>(null);
  const timeoutRef = useRef<NodeJS.Timeout>();

  const calculatePosition = () => {
    if (!triggerRef.current || !tooltipRef.current) return;

    const triggerRect = triggerRef.current.getBoundingClientRect();
    const tooltipRect = tooltipRef.current.getBoundingClientRect();

    let top, left;

    switch (direction) {
      case 'top':
        top = triggerRect.top - tooltipRect.height - 8;
        left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
        break;
      case 'bottom':
        top = triggerRect.bottom + 8;
        left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
        break;
      case 'left':
        top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
        left = triggerRect.left - tooltipRect.width - 8;
        break;
      case 'right':
        top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
        left = triggerRect.right + 8;
        break;
      default:
        top = triggerRect.top - tooltipRect.height - 8;
        left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
    }

    // Ensure the tooltip stays within the viewport
    if (left < 8) left = 8;
    if (left + tooltipRect.width > window.innerWidth)
      left = window.innerWidth - tooltipRect.width - 8;
    if (top < 8) top = 8;
    if (top + tooltipRect.height > window.innerHeight)
      top = window.innerHeight - tooltipRect.height - 8;

    setTooltipPosition({ top: Math.round(top), left: Math.round(left) });
  };

  const showTooltip = () => {
    clearTimeout(timeoutRef.current);
    timeoutRef.current = setTimeout(() => {
      setVisible(true);
      calculatePosition();
    }, showDelay);
  };

  const hideTooltip = () => {
    clearTimeout(timeoutRef.current);
    timeoutRef.current = setTimeout(() => {
      setVisible(false);
    }, hideDelay);
  };

  useEffect(() => {
    const handleMouseMove = (event: MouseEvent) => {
      if (visible && tooltipRef.current && triggerRef.current) {
        const tooltipRect = tooltipRef.current.getBoundingClientRect();
        const triggerRect = triggerRef.current.getBoundingClientRect();

        const isOutsideTooltip =
          event.clientX < tooltipRect.left ||
          event.clientX > tooltipRect.right ||
          event.clientY < tooltipRect.top ||
          event.clientY > tooltipRect.bottom;

        const isOutsideTrigger =
          event.clientX < triggerRect.left ||
          event.clientX > triggerRect.right ||
          event.clientY < triggerRect.top ||
          event.clientY > triggerRect.bottom;

        if (isOutsideTooltip && isOutsideTrigger) {
          hideTooltip();
        }
      }
    };

    const handleScroll = () => {
      if (visible) {
        hideTooltip();
      }
    };

    const handleResize = () => {
      if (visible) {
        calculatePosition();
      }
    };

    document.addEventListener('mousemove', handleMouseMove);
    window.addEventListener('scroll', handleScroll);
    window.addEventListener('resize', handleResize);

    return () => {
      document.removeEventListener('mousemove', handleMouseMove);
      window.removeEventListener('scroll', handleScroll);
      window.removeEventListener('resize', handleResize);
      clearTimeout(timeoutRef.current);
    };
  }, [visible]);

  return (
    <TooltipContainer
      ref={triggerRef}
      onMouseEnter={showTooltip}
      onMouseLeave={hideTooltip}
      onFocus={showTooltip}
      onBlur={hideTooltip}
    >
      {children}
      {visible &&
        ReactDOM.createPortal(
          <RPGUIRoot>
            <TooltipBox
              ref={tooltipRef}
              direction={direction}
              backgroundColor={backgroundColor}
              textColor={textColor}
              style={{ top: tooltipPosition.top, left: tooltipPosition.left }}
            >
              {content}
            </TooltipBox>
          </RPGUIRoot>,
          document.body
        )}
    </TooltipContainer>
  );
};

const TooltipContainer = styled.div`
  display: inline-block;
  cursor: inherit;
`;

const fadeIn = keyframes`
  from {
    opacity: 0;
    transform: scale(0.95);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
`;

interface TooltipBoxProps {
  direction: 'top' | 'bottom' | 'left' | 'right';
  backgroundColor: string;
  textColor: string;
}

const TooltipBox = styled.div<TooltipBoxProps>`
  position: fixed;
  z-index: 1000;
  background-color: ${({ backgroundColor }) => backgroundColor};
  color: ${({ textColor }) => textColor};
  padding: 8px;
  border-radius: 4px;
  font-size: 0.65rem;
  max-width: 250px;
  box-shadow: 0px 4px 8px rgba(0, 0, 0, 0.1);
  animation: ${fadeIn} 0.2s ease-out;
  line-height: 1.3;
`;
