<script lang="ts">
  import type { Snippet } from "svelte";

  let {
    content,
    placement: preferredPlacement = "top",
    children,
  }: { content: string; placement?: "top" | "bottom"; children?: Snippet } = $props();

  const TOOLTIP_GAP = 8;
  const TOOLTIP_MAX_WIDTH_PX = 352; // 22rem

  let wrapperEl = $state<HTMLDivElement | null>(null);
  let showTooltip = $state(false);
  let placement = $state<"top" | "bottom">("top");
  let leftPx = $state<number | null>(null); // null = centered (CSS), number = clamped px from wrapper left

  function updatePosition() {
    if (!wrapperEl) return;
    const rect = wrapperEl.getBoundingClientRect();
    const vw = window.innerWidth;
    const vh = window.innerHeight;

    const spaceAbove = rect.top;
    const spaceBelow = vh - rect.bottom;
    placement =
      preferredPlacement === "top"
        ? spaceAbove >= spaceBelow
          ? "top"
          : "bottom"
        : spaceBelow >= spaceAbove
          ? "bottom"
          : "top";

    const iconCenterX = rect.left + rect.width / 2;
    const idealLeft = iconCenterX - TOOLTIP_MAX_WIDTH_PX / 2;
    const clampedLeft = Math.max(
      TOOLTIP_GAP,
      Math.min(idealLeft, vw - TOOLTIP_MAX_WIDTH_PX - TOOLTIP_GAP),
    );
    leftPx = clampedLeft - rect.left;
  }

  function handleShow() {
    updatePosition();
    showTooltip = true;
  }

  function handleHide() {
    showTooltip = false;
    leftPx = null;
  }

  const placementClasses = $derived(
    placement === "top"
      ? "bottom-full mb-2"
      : "top-full mt-2",
  );
  const horizontalStyle = $derived(
    leftPx != null ? `left: ${leftPx}px; transform: none;` : "left: 50%; transform: translateX(-50%);",
  );
</script>

<div
  bind:this={wrapperEl}
  role="group"
  class="relative inline-flex focus-within:outline-none"
  onmouseenter={handleShow}
  onmouseleave={handleHide}
  onfocusin={handleShow}
  onfocusout={handleHide}
>
  {@render children?.()}
  {#if showTooltip}
    <div
      role="tooltip"
      class="absolute z-50 {placementClasses} px-3 py-2 text-xs font-normal text-stein-0 bg-stein-800 rounded-md shadow-lg min-w-56 max-w-88 text-center pointer-events-none whitespace-normal"
      style={horizontalStyle}
    >
      {content}
    </div>
  {/if}
</div>
