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

interface Props {
  open: boolean;
  onClose: () => void;
  children: ReactNode;
  title?: string;
}

// Past this drag distance, release dismisses the sheet.
const SWIPE_DISMISS_THRESHOLD_PX = 80;

export function BottomSheet({ open, onClose, children, title }: Props) {
  const [dragY, setDragY] = useState(0);
  const startYRef = useRef<number | null>(null);

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

  useEffect(() => {
    if (!open) {
      setDragY(0);
      startYRef.current = null;
    }
  }, [open]);

  function onTouchStart(e: TouchEvent<HTMLDivElement>) {
    const t = e.touches[0];
    if (!t) return;
    startYRef.current = t.clientY;
  }
  function onTouchMove(e: TouchEvent<HTMLDivElement>) {
    const t = e.touches[0];
    if (!t || startYRef.current === null) return;
    const dy = t.clientY - startYRef.current;
    // Clamp to downward drags so the sheet doesn't "rubber-band" up.
    if (dy > 0) setDragY(dy);
  }
  function onTouchEnd() {
    if (dragY > SWIPE_DISMISS_THRESHOLD_PX) {
      onClose();
    } else {
      setDragY(0);
    }
    startYRef.current = null;
  }

  if (!open) return null;

  return (
    <>
      <div
        className="fixed inset-0 z-40 bg-black/40"
        onClick={onClose}
        aria-hidden="true"
      />
      <div
        role="dialog"
        aria-modal="true"
        className={cn(
          'fixed inset-x-0 bottom-0 z-50 rounded-t-2xl border-t border-border bg-popover text-popover-foreground shadow-2xl',
          'motion-reduce:transition-none transition-transform duration-150 will-change-transform',
          'max-h-[70vh] flex flex-col',
        )}
        style={{
          transform: `translateY(${dragY}px)`,
          paddingBottom: 'env(safe-area-inset-bottom)',
        }}
      >
        <div
          onTouchStart={onTouchStart}
          onTouchMove={onTouchMove}
          onTouchEnd={onTouchEnd}
          className="flex flex-col items-center pt-2 pb-1 select-none touch-none"
        >
          <div className="w-10 h-1 bg-muted-foreground/40 rounded-full" />
          {title && (
            <div className="mt-1 text-sm font-medium text-muted-foreground">{title}</div>
          )}
        </div>
        <div className="flex-1 overflow-y-auto">{children}</div>
      </div>
    </>
  );
}
