// src/client/features/tasks/model/useTaskItemDrag.ts
// Composable for managing drag-and-drop events for individual task items
//
// KEY FIX: Uses global useDragState() so ALL TaskItems know which task is being
// dragged, regardless of which one initiated the drag. This fixes the core bug
// where dataTransfer.getData() returns "" during dragover events in most browsers.

import { ref, computed, type Ref } from 'vue';
import type { Task } from '../../../shared/api/repositories';
import { useDragState } from './useDragState';

const OUTDENT_THRESHOLD = 25;

interface UseTaskItemDragParams {
  task: Task;
  cardId: string;
  itemRef: Ref<HTMLElement | null>;
  onReorder: (draggedTaskId: string, targetTaskId: string, clientX: number, clientY: number) => void;
  onDragOver: (draggedTaskId: string, targetTaskId: string, clientX: number, clientY: number) => void;
  onDragLeave: (draggedTaskId: string) => void;
  onDragEnd: () => void;
}

export function useTaskItemDrag({
  task,
  cardId,
  itemRef,
  onReorder,
  onDragOver,
  onDragLeave,
  onDragEnd,
}: UseTaskItemDragParams) {
  const { draggedTaskId: globalDraggedId, startDrag, endDrag } = useDragState();

  const isOutdentZoneActive = ref(false);
  const isDragging = ref(false);
  const isDragOver = ref(false);

  const handleDragStart = (e: DragEvent) => {
    isDragging.value = true;
    // Set global state FIRST (this is what other TaskItems will read)
    startDrag(task.id, cardId);
    if (e.dataTransfer) {
      e.dataTransfer.setData('text/plain', task.id);
      e.dataTransfer.effectAllowed = 'move';
    }
  };

  const handleDragOver = (e: DragEvent) => {
    e.preventDefault();

    // READ from global state
    const draggedTaskId = globalDraggedId.value;

    // If dragging over ourselves — DON'T stopPropagation!
    // Let the event bubble up to the card body handler, which will
    // show a placeholder at the end of the list. This is critical
    // for the last item in the list — there's nothing below it,
    // so the body handler is the only way to get a placeholder.
    if (!draggedTaskId || draggedTaskId === task.id) return;

    // Only stop propagation for valid cross-item drags
    e.stopPropagation();

    isDragOver.value = true;
    if (e.dataTransfer) {
      e.dataTransfer.dropEffect = 'move';
    }

    // Check outdent zone
    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
    isOutdentZoneActive.value = e.clientX < rect.left + OUTDENT_THRESHOLD;

    // Emit to parent (TaskCard) for placeholder calculation
    onDragOver(draggedTaskId, task.id, e.clientX, e.clientY);
  };

  const handleDragLeave = (e: DragEvent) => {
    const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();
    const { clientX: x, clientY: y } = e;

    // Only clear if cursor actually left this element's bounding box
    if (x < rect.left || x >= rect.right || y < rect.top || y >= rect.bottom) {
      isDragOver.value = false;
      isOutdentZoneActive.value = false;

      const draggedTaskId = globalDraggedId.value;
      if (draggedTaskId) {
        onDragLeave(draggedTaskId);
      }
    }
  };

  const handleDrop = (e: DragEvent) => {
    e.preventDefault();

    isDragOver.value = false;
    isOutdentZoneActive.value = false;

    // READ from global state
    const draggedTaskId = globalDraggedId.value;

    // If dropping on ourselves, let it bubble to body handler
    if (!draggedTaskId || draggedTaskId === task.id) return;

    e.stopPropagation();
    onReorder(draggedTaskId, task.id, e.clientX, e.clientY);
  };

  const handleDragEnd = () => {
    isDragging.value = false;
    isDragOver.value = false;
    isOutdentZoneActive.value = false;
    endDrag(); // Clear global state
    onDragEnd();
  };

  return {
    isDragging,
    isDragOver,
    isOutdentZoneActive,
    OUTDENT_THRESHOLD,
    handleDragStart,
    handleDragOver,
    handleDragLeave,
    handleDrop,
    handleDragEnd,
  };
}