'use client';

import { useCallback, useEffect, useRef, useState, type MouseEvent as ReactMouseEvent } from 'react';

const DRAG_THRESHOLD_PX = 6;

interface UseChatDragSelectionOptions {
  selectionMode: boolean;
  enterSelectionMode: (messageId: string) => void;
  addSelectedMessage: (messageId: string) => void;
}

const dragSuppressedUntilRef = { current: 0 };

export function suppressChatDragSelection(durationMs = 400) {
  dragSuppressedUntilRef.current = Date.now() + durationMs;
}

function isDragSuppressed() {
  return Date.now() < dragSuppressedUntilRef.current;
}

export function useChatDragSelection({
  selectionMode,
  enterSelectionMode,
  addSelectedMessage
}: UseChatDragSelectionOptions) {
  const [isDragging, setIsDragging] = useState(false);
  const visitedRef = useRef<Set<string>>(new Set());
  const pendingDragRef = useRef<{ messageId: string; x: number; y: number } | null>(null);

  const startDragSelection = useCallback(
    (messageId: string) => {
      if (isDragSuppressed()) return;
      setIsDragging(true);
      visitedRef.current = new Set([messageId]);
      if (!selectionMode) {
        enterSelectionMode(messageId);
      } else {
        addSelectedMessage(messageId);
      }
    },
    [addSelectedMessage, enterSelectionMode, selectionMode]
  );

  const handleMessagePointerDown = useCallback(
    (messageId: string, event: ReactMouseEvent) => {
      if (event.button !== 0 || isDragSuppressed()) return;
      pendingDragRef.current = { messageId, x: event.clientX, y: event.clientY };
    },
    []
  );

  const handleDragEnterMessage = useCallback(
    (messageId: string) => {
      if (!isDragging || visitedRef.current.has(messageId)) return;
      visitedRef.current.add(messageId);
      addSelectedMessage(messageId);
    },
    [addSelectedMessage, isDragging]
  );

  const endDragSelection = useCallback(() => {
    pendingDragRef.current = null;
    setIsDragging(false);
    visitedRef.current.clear();
  }, []);

  useEffect(() => {
    const onMouseMove = (event: MouseEvent) => {
      const pending = pendingDragRef.current;
      if (!pending || isDragSuppressed()) return;
      const distance = Math.hypot(event.clientX - pending.x, event.clientY - pending.y);
      if (distance < DRAG_THRESHOLD_PX) return;
      const messageId = pending.messageId;
      pendingDragRef.current = null;
      startDragSelection(messageId);
    };

    window.addEventListener('mousemove', onMouseMove);
    window.addEventListener('mouseup', endDragSelection);
    return () => {
      window.removeEventListener('mousemove', onMouseMove);
      window.removeEventListener('mouseup', endDragSelection);
    };
  }, [endDragSelection, startDragSelection]);

  return {
    isDragging,
    handleMessagePointerDown,
    handleDragEnterMessage,
    endDragSelection
  };
}
