'use client';

import React, { 
  useState, 
  useRef, 
  useEffect, 
  forwardRef, 
  ReactNode, 
  CSSProperties,
  useCallback
} from 'react';

interface TooltipProps {
  children: ReactNode;
  content: ReactNode;
  side?: 'top' | 'bottom' | 'left' | 'right';
  delay?: number;
  className?: string;
  contentClassName?: string;
}

interface TooltipContentProps {
  children: ReactNode;
  className?: string;
  style?: CSSProperties;
}

interface TooltipTriggerProps {
  children: ReactNode;
  asChild?: boolean;
  className?: string;
}

const Tooltip = ({ 
  children, 
  content, 
  side = 'top', 
  delay = 200,
  className = '',
  contentClassName = ''
}: TooltipProps) => {
  const [isVisible, setIsVisible] = useState(false);
  const [position, setPosition] = useState({ top: 0, left: 0 });
  const triggerRef = useRef<HTMLDivElement>(null);
  const tooltipRef = useRef<HTMLDivElement>(null);
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);

  const hideTooltip = useCallback(() => {
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
      timeoutRef.current = null;
    }
    setIsVisible(false);
  }, []);

  const showTooltip = useCallback(() => {
    if (!triggerRef.current) return;
    
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }
    
    timeoutRef.current = setTimeout(() => {
      const triggerRect = triggerRef.current!.getBoundingClientRect();
      let top = 0;
      let left = 0;
      
      switch (side) {
        case 'top':
          top = triggerRect.top - 5;
          left = triggerRect.left + (triggerRect.width / 2);
          break;
        case 'bottom':
          top = triggerRect.bottom + 5;
          left = triggerRect.left + (triggerRect.width / 2);
          break;
        case 'left':
          top = triggerRect.top + (triggerRect.height / 2);
          left = triggerRect.left - 5;
          break;
        case 'right':
          top = triggerRect.top + (triggerRect.height / 2);
          left = triggerRect.right + 5;
          break;
      }
      
      setPosition({ top, left });
      setIsVisible(true);
    }, delay);
  }, [delay, side]);

  useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
    };
  }, []);

  useEffect(() => {
    const handleClickOutside = (event: MouseEvent) => {
      if (
        tooltipRef.current && 
        !tooltipRef.current.contains(event.target as Node) &&
        triggerRef.current && 
        !triggerRef.current.contains(event.target as Node)
      ) {
        hideTooltip();
      }
    };

    document.addEventListener('mousedown', handleClickOutside);
    return () => document.removeEventListener('mousedown', handleClickOutside);
  }, [hideTooltip]);

  useEffect(() => {
    const handleEscape = (event: KeyboardEvent) => {
      if (event.key === 'Escape') {
        hideTooltip();
      }
    };

    document.addEventListener('keydown', handleEscape);
    return () => document.removeEventListener('keydown', handleEscape);
  }, [hideTooltip]);

  return (
    <div 
      className={`relative inline-block ${className}`}
      ref={triggerRef}
      onMouseEnter={showTooltip}
      onMouseLeave={hideTooltip}
      onFocus={showTooltip}
      onBlur={hideTooltip}
    >
      {children}
      
      {isVisible && (
        <div
          ref={tooltipRef}
          className={`fixed z-50 ${contentClassName}`}
          style={{
            top: `${position.top}px`,
            left: `${position.left}px`,
            transform: `translate(-50%, ${side === 'top' ? '-100%' : side === 'bottom' ? '0' : '-50%'})`
          }}
          role="tooltip"
        >
          <TooltipContent className={contentClassName} side={side}>
            {content}
          </TooltipContent>
        </div>
      )}
    </div>
  );
};

interface TooltipContentPropsExtended extends TooltipContentProps {
  side?: 'top' | 'bottom' | 'left' | 'right';
}

const TooltipContent = forwardRef<HTMLDivElement, TooltipContentPropsExtended>(
  ({ children, className = '', style, side = 'top' }, ref) => {
    const getArrowStyle = (): CSSProperties => {
      const baseStyle: CSSProperties = {
        position: 'absolute',
        width: '8px',
        height: '8px',
        backgroundColor: 'var(--surface-raised)',
        transform: 'rotate(45deg)'
      };

      switch (side) {
        case 'top':
          return {
            ...baseStyle,
            bottom: '-4px',
            left: '50%',
            transform: 'translateX(-50%) rotate(45deg)'
          };
        case 'bottom':
          return {
            ...baseStyle,
            top: '-4px',
            left: '50%',
            transform: 'translateX(-50%) rotate(45deg)'
          };
        case 'left':
          return {
            ...baseStyle,
            right: '-4px',
            top: '50%',
            transform: 'translateY(-50%) rotate(45deg)'
          };
        case 'right':
          return {
            ...baseStyle,
            left: '-4px',
            top: '50%',
            transform: 'translateY(-50%) rotate(45deg)'
          };
        default:
          return {
            ...baseStyle,
            bottom: '-4px',
            left: '50%',
            transform: 'translateX(-50%) rotate(45deg)'
          };
      }
    };

    return (
      <div
        ref={ref}
        className={`
          bg-var-surface-raised text-var-text text-sm 
          px-3 py-1.5 rounded-md 
          shadow-var-modal border border-var-border
          ${className}
        `}
        style={style}
      >
        {children}
        <div style={getArrowStyle()} />
      </div>
    );
  }
);

TooltipContent.displayName = 'TooltipContent';

const TooltipTrigger = forwardRef<HTMLDivElement, TooltipTriggerProps>(
  ({ children, className = '' }, ref) => {
    return (
      <div ref={ref} className={`inline-block ${className}`}>
        {children}
      </div>
    );
  }
);

TooltipTrigger.displayName = 'TooltipTrigger';

export { Tooltip, TooltipTrigger, TooltipContent };