import { useState, useEffect, useRef, useCallback } from 'react';
import { cn } from '@/lib/utils';

/**
 * TooltipProps - Propriétés du composant Tooltip
 *
 * @interface TooltipProps
 */
export interface TooltipProps {
  /**
   * Contenu du tooltip (texte ou élément React)
   */
  content: React.ReactNode;

  /**
   * Élément enfant qui déclenche le tooltip
   */
  children: React.ReactNode;

  /**
   * Position du tooltip par rapport à l'élément
   *
   * - `top`: Au-dessus
   * - `bottom`: En-dessous
   * - `left`: À gauche
   * - `right`: À droite
   *
   * @default 'top'
   */
  position?: 'top' | 'bottom' | 'left' | 'right';

  /**
   * Événement qui déclenche l'affichage du tooltip
   *
   * - `hover`: Au survol (par défaut)
   * - `click`: Au clic
   * - `focus`: Au focus
   *
   * @default 'hover'
   */
  trigger?: 'hover' | 'click' | 'focus';

  /**
   * Délai avant l'affichage en millisecondes
   *
   * @default 200
   */
  delay?: number;

  /**
   * Si `true`, affiche une flèche pointant vers l'élément
   *
   * @default true
   */
  showArrow?: boolean;

  /**
   * Largeur maximale du tooltip en pixels
   *
   * @default 300
   */
  maxWidth?: number;

  /**
   * Si `true`, désactive le tooltip
   *
   * @default false
   */
  disabled?: boolean;

  /**
   * Classes CSS personnalisées
   */
  className?: string;
}

/**
 * Tooltip - Composant de tooltip avec design system Kodo
 *
 * Composant de tooltip avec :
 * - Positionnement intelligent (flip et shift automatiques)
 * - Plusieurs triggers (hover, click, focus)
 * - Délai configurable
 * - Flèche optionnelle
 * - Gestion du viewport
 *
 * @example
 * ```tsx
 * // Tooltip simple au survol
 * <Tooltip content="Information supplémentaire">
 *   <button>Hover me</button>
 * </Tooltip>
 * ```
 *
 * @example
 * ```tsx
 * // Tooltip avec position et trigger personnalisés
 * <Tooltip
 *   content="Cliquez pour plus d'infos"
 *   position="bottom"
 *   trigger="click"
 *   delay={300}
 * >
 *   <button>Click me</button>
 * </Tooltip>
 * ```
 *
 * @component
 * @param {TooltipProps} props - Propriétés du composant
 * @returns {JSX.Element} Wrapper avec tooltip positionné
 */
export function Tooltip({
  content,
  children,
  position = 'top',
  trigger = 'hover',
  delay = 200,
  showArrow = true,
  maxWidth = 300,
  disabled = false,
  className,
}: TooltipProps) {
  const [visible, setVisible] = useState(false);
  const [isMounted, setIsMounted] = useState(false);
  const [calculatedPosition, setCalculatedPosition] = useState(position);
  const [tooltipStyle, setTooltipStyle] = useState<React.CSSProperties>({});
  const timeoutRef = useRef<NodeJS.Timeout | null>(null);
  const hideTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const wrapperRef = useRef<HTMLDivElement>(null);
  const tooltipRef = useRef<HTMLDivElement>(null);

  // Calcul du positionnement avec flip et shift
  const calculatePosition = useCallback(() => {
    if (!wrapperRef.current || !tooltipRef.current || !visible) return;

    const wrapperRect = wrapperRef.current.getBoundingClientRect();
    const tooltipRect = tooltipRef.current.getBoundingClientRect();
    const viewportWidth = window.innerWidth;
    const viewportHeight = window.innerHeight;
    const margin = 8;

    let newPosition = position;
    let offsetX = 0;
    let offsetY = 0;

    // Flip: inverser la position si le tooltip sort de l'écran
    switch (position) {
      case 'top':
        if (wrapperRect.top - tooltipRect.height - margin < 0) {
          newPosition = 'bottom';
        }
        break;
      case 'bottom':
        if (wrapperRect.bottom + tooltipRect.height + margin > viewportHeight) {
          newPosition = 'top';
        }
        break;
      case 'left':
        if (wrapperRect.left - tooltipRect.width - margin < 0) {
          newPosition = 'right';
        }
        break;
      case 'right':
        if (wrapperRect.right + tooltipRect.width + margin > viewportWidth) {
          newPosition = 'left';
        }
        break;
    }

    // Shift: ajuster la position pour rester dans la viewport
    if (newPosition === 'top' || newPosition === 'bottom') {
      const centerX = wrapperRect.left + wrapperRect.width / 2;
      const tooltipHalfWidth = tooltipRect.width / 2;
      const minX = margin;
      const maxX = viewportWidth - margin;

      if (centerX - tooltipHalfWidth < minX) {
        offsetX = minX - (centerX - tooltipHalfWidth);
      } else if (centerX + tooltipHalfWidth > maxX) {
        offsetX = maxX - (centerX + tooltipHalfWidth);
      }
    } else {
      const centerY = wrapperRect.top + wrapperRect.height / 2;
      const tooltipHalfHeight = tooltipRect.height / 2;
      const minY = margin;
      const maxY = viewportHeight - margin;

      if (centerY - tooltipHalfHeight < minY) {
        offsetY = minY - (centerY - tooltipHalfHeight);
      } else if (centerY + tooltipHalfHeight > maxY) {
        offsetY = maxY - (centerY + tooltipHalfHeight);
      }
    }

    setCalculatedPosition(newPosition);
    setTooltipStyle({
      ...(offsetX !== 0 && {
        transform: `translate(calc(-50% + ${offsetX}px), 0)`,
      }),
      ...(offsetY !== 0 && {
        transform: `translate(0, calc(-50% + ${offsetY}px))`,
      }),
    });
  }, [position, visible]);

  useEffect(() => {
    if (visible) {
      setIsMounted(true);
      calculatePosition();
    }
  }, [visible, calculatePosition]);

  useEffect(() => {
    if (isMounted && visible) {
      calculatePosition();
    }
  }, [isMounted, visible, calculatePosition]);

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

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

  const handleClick = () => {
    if (trigger === 'click') {
      setVisible(!visible);
    }
  };

  const triggerProps = {
    hover: {
      onMouseEnter: showTooltip,
      onMouseLeave: hideTooltip,
    },
    click: {
      onClick: handleClick,
    },
    focus: {
      onFocus: showTooltip,
      onBlur: hideTooltip,
    },
  }[trigger];

  const positionClasses = {
    top: 'bottom-full left-1/2 -translate-x-1/2 mb-2',
    bottom: 'top-full left-1/2 -translate-x-1/2 mt-2',
    left: 'right-full top-1/2 -translate-y-1/2 mr-2',
    right: 'left-full top-1/2 -translate-y-1/2 ml-2',
  };

  const arrowClasses = {
    top: 'top-full left-1/2 -translate-x-1/2 border-t-kodo-ink border-l-transparent border-r-transparent border-b-transparent',
    bottom:
      'bottom-full left-1/2 -translate-x-1/2 border-b-kodo-ink border-l-transparent border-r-transparent border-t-transparent',
    left: 'left-full top-1/2 -translate-y-1/2 border-l-kodo-ink border-t-transparent border-b-transparent border-r-transparent',
    right:
      'right-full top-1/2 -translate-y-1/2 border-r-kodo-ink border-t-transparent border-b-transparent border-l-transparent',
  };

  useEffect(() => {
    return () => {
      if (timeoutRef.current) {
        clearTimeout(timeoutRef.current);
      }
      if (hideTimeoutRef.current) {
        clearTimeout(hideTimeoutRef.current);
      }
    };
  }, []);

  if (disabled) {
    return <>{children}</>;
  }

  const tooltipContent = (
    <>
      {isMounted && (
        <div
          ref={tooltipRef}
          className={cn(
            'absolute z-50 px-3 py-1.5 text-sm text-white bg-kodo-ink rounded-md shadow-lg',
            'border border-kodo-steel pointer-events-none',
            'transition-all duration-200',
            positionClasses[calculatedPosition],
            visible ? 'opacity-100 scale-100' : 'opacity-0 scale-95',
            className,
          )}
          role="tooltip"
          style={{ maxWidth: `${maxWidth}px`, ...tooltipStyle }}
        >
          {content}
          {showArrow && (
            <div
              className={cn(
                'absolute w-0 h-0 border-4',
                arrowClasses[calculatedPosition],
              )}
            />
          )}
        </div>
      )}
    </>
  );

  return (
    <div ref={wrapperRef} className="relative inline-block" {...triggerProps}>
      {children}
      {tooltipContent}
    </div>
  );
}
