import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';

type PopoverProps = {
  opened: boolean;
  onClose: () => void;
  target: HTMLElement | null;
  children: React.ReactNode;
  placement?: 'auto' | 'top' | 'bottom';
  width?: number;
  className?: string;
};

const MARGIN = 8;

const Popover = ({
  opened,
  onClose,
  target,
  children,
  placement = 'auto',
  width = 240,
  className = '',
}: PopoverProps) => {
  const popoverRef = useRef<HTMLDivElement>(null);
  const [pos, setPos] = useState<{ top: number; left: number; placement: 'top' | 'bottom' } | null>(
    null
  );

  useLayoutEffect(() => {
    if (!opened || !target) {
      setPos(null);
      return;
    }
    const rect = target.getBoundingClientRect();
    const popHeight = popoverRef.current?.offsetHeight ?? 200;
    const popWidth = popoverRef.current?.offsetWidth ?? width;

    const spaceBelow = window.innerHeight - rect.bottom;
    const spaceAbove = rect.top;

    let actualPlacement: 'top' | 'bottom';
    if (placement === 'auto') {
      actualPlacement = spaceBelow >= popHeight + MARGIN ? 'bottom' : 'top';
    } else {
      actualPlacement = placement;
    }

    if (actualPlacement === 'top' && spaceAbove < popHeight + MARGIN) {
      actualPlacement = 'bottom';
    }

    let top =
      actualPlacement === 'bottom'
        ? rect.bottom + MARGIN
        : rect.top - popHeight - MARGIN;

    let left = rect.left + rect.width / 2 - popWidth / 2;
    if (left < MARGIN) left = MARGIN;
    if (left + popWidth > window.innerWidth - MARGIN) {
      left = window.innerWidth - popWidth - MARGIN;
    }
    if (top < MARGIN) top = MARGIN;

    setPos({ top, left, placement: actualPlacement });
  }, [opened, target, placement, width]);

  useEffect(() => {
    if (!opened) return;
    const onKey = (e: KeyboardEvent) => {
      if (e.key === 'Escape') onClose();
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [opened, onClose]);

  if (!opened) return null;

  return (
    <>
      <div
        className="fixed inset-0 z-[100]"
        onClick={onClose}
        onContextMenu={(e) => {
          e.preventDefault();
          onClose();
        }}
      />
      <div
        ref={popoverRef}
        style={{
          top: pos?.top ?? -9999,
          left: pos?.left ?? -9999,
          width,
          visibility: pos ? 'visible' : 'hidden',
        }}
        className={`fixed z-[101] tg-fade-in rounded-2xl shadow-xl shadow-black/20 overflow-hidden
          bg-[var(--tg-bg)] border border-[var(--tg-divider)] ${className}`}
        onClick={(e) => e.stopPropagation()}
      >
        {children}
      </div>
    </>
  );
};

export default Popover;
