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

interface Props {
  label: string;
  isActive: boolean;
  onTap: () => void;
  onClose: () => void;
  canClose: boolean;
}

const CLOSE_THRESHOLD = 60;
const MAX_TRAVEL = 120;
const VERTICAL_BAIL = 30;

// Pane tab with horizontal swipe-to-close (mobile only). Tracks horizontal
// finger movement; if vertical exceeds VERTICAL_BAIL the gesture is cancelled
// (so vertical scroll still works). On release past CLOSE_THRESHOLD, the
// onClose callback fires. Otherwise the tab snaps back. Hand-rolled per spec.
export function SwipeablePaneTab({ label, isActive, onTap, onClose, canClose }: Props) {
  const [translateX, setTranslateX] = useState(0);
  const [dragging, setDragging] = useState(false);
  const startRef = useRef<{ x: number; y: number; bailed: boolean } | null>(null);

  const onTouchStart = (e: TouchEvent) => {
    if (!canClose) return;
    const t = e.touches[0];
    if (!t) return;
    startRef.current = { x: t.clientX, y: t.clientY, bailed: false };
    setDragging(true);
  };

  const onTouchMove = (e: TouchEvent) => {
    const start = startRef.current;
    if (!start || start.bailed) return;
    const t = e.touches[0];
    if (!t) return;
    const dx = t.clientX - start.x;
    const dy = t.clientY - start.y;
    if (Math.abs(dy) > VERTICAL_BAIL) {
      start.bailed = true;
      setTranslateX(0);
      setDragging(false);
      return;
    }
    if (dx < 0) {
      setTranslateX(Math.max(dx, -MAX_TRAVEL));
    } else {
      setTranslateX(0);
    }
  };

  const onTouchEnd = () => {
    const start = startRef.current;
    startRef.current = null;
    setDragging(false);
    if (!start || start.bailed) {
      setTranslateX(0);
      return;
    }
    const tx = translateX;
    if (tx <= -CLOSE_THRESHOLD) {
      onClose();
      // Don't reset translateX; the parent will unmount this tab.
    } else {
      setTranslateX(0);
    }
  };

  // Opacity fades from 1 -> 0.4 as the tab approaches the close threshold.
  const opacity =
    translateX < 0
      ? Math.max(0.4, 1 - (Math.abs(translateX) / CLOSE_THRESHOLD) * 0.6)
      : 1;

  return (
    <button
      type="button"
      onClick={onTap}
      onTouchStart={onTouchStart}
      onTouchMove={onTouchMove}
      onTouchEnd={onTouchEnd}
      onTouchCancel={onTouchEnd}
      style={{
        transform: `translateX(${translateX}px)`,
        opacity,
        // Only animate when releasing (snap-back); during drag the transform
        // tracks the finger 1:1 for a tight feel.
        transition: dragging ? undefined : 'transform 0.15s ease, opacity 0.15s ease',
      }}
      className={cn(
        'shrink-0 px-3 py-2 text-xs rounded min-h-[44px] min-w-[44px]',
        isActive
          ? 'bg-background text-foreground border'
          : 'text-muted-foreground hover:bg-muted/40',
      )}
      aria-current={isActive ? 'true' : undefined}
    >
      <span className="truncate max-w-[140px] inline-block">{label}</span>
    </button>
  );
}
