<template>
  <div class="relative inline-block">
    <div @mouseenter="showTooltip" @mouseleave="hideTooltip">
      <slot></slot>
    </div>
    <div v-show="isVisible" ref="tooltipEl" class="tooltip fixed z-50 px-2 py-1 text-xs font-medium text-white bg-gray-800 rounded shadow-lg whitespace-nowrap" :style="tooltipStyle">
      {{ text }}
      <div class="absolute w-2 h-2 bg-gray-800 transform rotate-45" :style="arrowStyle"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
  import { ref, computed, onMounted, onBeforeUnmount } from 'vue';

  const props = defineProps<{
    text: string;
    position?: 'top' | 'right' | 'bottom' | 'left';
    offset?: number;
  }>();

  const isVisible = ref(false);
  const tooltipEl = ref<HTMLElement | null>(null);
  const position = computed(() => props.position || 'top');
  const offset = computed(() => props.offset || 8);

  // Dynamic styles for tooltip and arrow
  const tooltipStyle = ref({
    left: '0px',
    top: '0px',
  });

  const arrowStyle = ref({
    left: '50%',
    top: '100%',
    transform: 'translate(-50%, -50%) rotate(45deg)',
  });

  const updatePosition = (event: MouseEvent) => {
    if (!isVisible.value || !tooltipEl.value) return;

    const tooltip = tooltipEl.value;
    const tooltipRect = tooltip.getBoundingClientRect();
    const padding = 10; // Padding from screen edges

    let left = event.clientX;
    let top = event.clientY;

    // Calculate positions based on available space
    const spaceAbove = top;
    const spaceBelow = window.innerHeight - top;
    const spaceLeft = left;
    const spaceRight = window.innerWidth - left;

    // Determine best position
    let finalPosition = position.value;
    if (finalPosition === 'top' && spaceAbove < tooltipRect.height + padding) {
      finalPosition = spaceBelow > tooltipRect.height + padding ? 'bottom' : 'right';
    } else if (finalPosition === 'bottom' && spaceBelow < tooltipRect.height + padding) {
      finalPosition = spaceAbove > tooltipRect.height + padding ? 'top' : 'right';
    } else if (finalPosition === 'left' && spaceLeft < tooltipRect.width + padding) {
      finalPosition = spaceRight > tooltipRect.width + padding ? 'right' : 'top';
    } else if (finalPosition === 'right' && spaceRight < tooltipRect.width + padding) {
      finalPosition = spaceLeft > tooltipRect.width + padding ? 'left' : 'top';
    }

    // Position tooltip based on final position
    switch (finalPosition) {
      case 'top':
        left -= tooltipRect.width / 2;
        top -= tooltipRect.height + offset.value;
        arrowStyle.value = {
          left: '50%',
          top: '100%',
          transform: 'translate(-50%, -50%) rotate(45deg)',
        };
        break;
      case 'bottom':
        left -= tooltipRect.width / 2;
        top += offset.value;
        arrowStyle.value = {
          left: '50%',
          top: '0',
          transform: 'translate(-50%, -50%) rotate(45deg)',
        };
        break;
      case 'left':
        left -= tooltipRect.width + offset.value;
        top -= tooltipRect.height / 2;
        arrowStyle.value = {
          left: '100%',
          top: '50%',
          transform: 'translate(-50%, -50%) rotate(45deg)',
        };
        break;
      case 'right':
        left += offset.value;
        top -= tooltipRect.height / 2;
        arrowStyle.value = {
          left: '0',
          top: '50%',
          transform: 'translate(-50%, -50%) rotate(45deg)',
        };
        break;
    }

    // Ensure tooltip stays within screen bounds
    left = Math.max(padding, Math.min(left, window.innerWidth - tooltipRect.width - padding));
    top = Math.max(padding, Math.min(top, window.innerHeight - tooltipRect.height - padding));

    tooltipStyle.value = {
      left: `${left}px`,
      top: `${top}px`,
    };
  };

  const showTooltip = (event: MouseEvent) => {
    isVisible.value = true;
    // Wait for next tick to ensure tooltip is rendered
    setTimeout(() => updatePosition(event), 0);
  };

  const hideTooltip = () => {
    isVisible.value = false;
  };

  // Track mouse movement when tooltip is visible
  const handleMouseMove = (event: MouseEvent) => {
    if (isVisible.value) {
      updatePosition(event);
    }
  };

  onMounted(() => {
    window.addEventListener('mousemove', handleMouseMove);
  });

  onBeforeUnmount(() => {
    window.removeEventListener('mousemove', handleMouseMove);
  });
</script>
