import React, { useState, useRef, useEffect } from "react";
import styles from "../styles/tooltip.module.css";

export interface TooltipProps {
  content: string | React.ReactNode;
  children: React.ReactNode;
  position?: "top" | "bottom" | "left" | "right";
  delay?: number;
  disabled?: boolean;
  className?: string | undefined;
  maxWidth?: number;
}

export const Tooltip: React.FC<TooltipProps> = ({
  content,
  children,
  position = "top",
  delay = 500,
  disabled = false,
  className = "",
  maxWidth = 250,
}) => {
  const [isVisible, setIsVisible] = useState(false);
  const [actualPosition, setActualPosition] = useState(position);
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
  const triggerRef = useRef<HTMLDivElement>(null);
  const tooltipRef = useRef<HTMLDivElement>(null);

  const showTooltip = () => {
    if (disabled || !content) {
      return;
    }

    timeoutRef.current = setTimeout(() => {
      setIsVisible(true);
    }, delay);
  };

  const hideTooltip = () => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }
    setIsVisible(false);
  };

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

    const triggerRect = triggerRef.current.getBoundingClientRect();
    const tooltipRect = tooltipRef.current.getBoundingClientRect();
    const viewport = {
      width: window.innerWidth,
      height: window.innerHeight,
    };

    let newPosition = position;

    // Check if tooltip fits in the preferred position
    switch (position) {
      case "top":
        if (triggerRect.top - tooltipRect.height < 0) {
          newPosition = "bottom";
        }
        break;
      case "bottom":
        if (triggerRect.bottom + tooltipRect.height > viewport.height) {
          newPosition = "top";
        }
        break;
      case "left":
        if (triggerRect.left - tooltipRect.width < 0) {
          newPosition = "right";
        }
        break;
      case "right":
        if (triggerRect.right + tooltipRect.width > viewport.width) {
          newPosition = "left";
        }
        break;
    }

    setActualPosition(newPosition);
  };

  useEffect(() => {
    if (isVisible) {
      calculatePosition();
    }
  }, [isVisible]);

  const tooltipClasses = [
    styles.tooltip,
    styles[`tooltip--${actualPosition}`],
    isVisible ? styles["tooltip--visible"] : "",
    className,
  ]
    .filter(Boolean)
    .join(" ");

  return (
    <div
      className={styles.tooltipContainer}
      ref={triggerRef}
      onMouseEnter={showTooltip}
      onMouseLeave={hideTooltip}
      onFocus={showTooltip}
      onBlur={hideTooltip}
    >
      {children}
      {isVisible && content && (
        <div
          ref={tooltipRef}
          className={tooltipClasses}
          style={{ maxWidth: `${maxWidth}px` }}
          role="tooltip"
          aria-hidden={!isVisible}
        >
          <div className={styles.tooltipContent}>{content}</div>
          <div className={styles.tooltipArrow} />
        </div>
      )}
    </div>
  );
};

export default Tooltip;
