'use client';

import { useLayoutEffect, useRef, useState, type CSSProperties, type RefObject } from 'react';

const VIEWPORT_PADDING = 12;
const DEFAULT_GAP = 8;

export type AnchoredPanelAlign = 'start' | 'stretch';

type UseAnchoredPanelPositionArgs = {
  open: boolean;
  /** Element the panel should attach to (field / trigger shell). */
  anchorRef: RefObject<HTMLElement | null>;
  /** Prefer aligning the panel's inline-start with the anchor's inline-start. */
  align?: AnchoredPanelAlign;
  gap?: number;
};

/**
 * Positions a panel with `position: fixed`, clamped to the viewport.
 * Flips above the anchor when there is not enough room below.
 * Handles LTR/RTL via `document.documentElement.dir`.
 */
export function useAnchoredPanelPosition({
  open,
  anchorRef,
  align = 'start',
  gap = DEFAULT_GAP,
}: UseAnchoredPanelPositionArgs) {
  const panelRef = useRef<HTMLDivElement>(null);
  const [style, setStyle] = useState<CSSProperties | undefined>(undefined);

  useLayoutEffect(() => {
    if (!open) {
      setStyle(undefined);
      return;
    }

    function update() {
      const anchor = anchorRef.current;
      const panel = panelRef.current;
      if (!anchor || !panel) return;

      const anchorRect = anchor.getBoundingClientRect();
      const panelRect = panel.getBoundingClientRect();
      const vw = window.innerWidth;
      const vh = window.innerHeight;
      const isRtl = document.documentElement.dir === 'rtl';

      let width =
        align === 'stretch'
          ? Math.min(anchorRect.width, vw - VIEWPORT_PADDING * 2)
          : Math.min(panelRect.width || panel.offsetWidth, vw - VIEWPORT_PADDING * 2);

      if (width < 1) width = Math.min(280, vw - VIEWPORT_PADDING * 2);

      let left: number;
      if (align === 'stretch') {
        left = anchorRect.left;
      } else if (isRtl) {
        left = anchorRect.right - width;
      } else {
        left = anchorRect.left;
      }
      left = Math.max(VIEWPORT_PADDING, Math.min(left, vw - width - VIEWPORT_PADDING));

      const height = panelRect.height || panel.offsetHeight;
      let top = anchorRect.bottom + gap;
      if (top + height > vh - VIEWPORT_PADDING) {
        const above = anchorRect.top - height - gap;
        top = above >= VIEWPORT_PADDING ? above : Math.max(VIEWPORT_PADDING, vh - height - VIEWPORT_PADDING);
      }

      setStyle({
        position: 'fixed',
        top,
        left,
        width,
        zIndex: 50,
      });
    }

    update();
    // Second pass after fonts/layout settle panel size.
    const raf = window.requestAnimationFrame(update);
    window.addEventListener('resize', update);
    window.addEventListener('scroll', update, true);
    return () => {
      window.cancelAnimationFrame(raf);
      window.removeEventListener('resize', update);
      window.removeEventListener('scroll', update, true);
    };
  }, [align, anchorRef, gap, open]);

  return { panelRef, style };
}
