// Rôle : fournit le moteur bas niveau de drag par pointeur.
// Gère uniquement la cible DOM, before/after et le cycle pointer down/move/up.
// Préférer useGroupedReorder pour les réorganisations applicatives d'outils.
import { useEffect, useRef, useState } from "react";

function getDefaultPlacement(event, element) {
  const rect = element.getBoundingClientRect();
  return event.clientY > rect.top + rect.height / 2 ? "after" : "before";
}

export function usePointerReorder({
  targetSelector,
  getTargetId,
  canDropOn = () => true,
  getPlacement = getDefaultPlacement,
  onMove
}) {
  const [draggingId, setDraggingId] = useState("");
  const [dropTarget, setDropTarget] = useState({ id: "", placement: "before" });
  const optionsRef = useRef({ getTargetId, canDropOn, getPlacement, onMove });

  useEffect(() => {
    optionsRef.current = { getTargetId, canDropOn, getPlacement, onMove };
  }, [canDropOn, getPlacement, getTargetId, onMove]);

  useEffect(() => {
    if (!draggingId) return undefined;

    function getDropTarget(event) {
      const { getTargetId, canDropOn, getPlacement } = optionsRef.current;
      const elements = document.elementsFromPoint?.(event.clientX, event.clientY) || [document.elementFromPoint(event.clientX, event.clientY)].filter(Boolean);
      for (const element of elements) {
        const target = element?.closest?.(targetSelector);
        if (!target || !canDropOn(target, draggingId)) continue;
        const targetId = getTargetId(target);
        if (targetId === draggingId) continue;
        return {
          id: targetId,
          placement: getPlacement(event, target)
        };
      }
      return { id: "", placement: "before" };
    }

    function handlePointerMove(event) {
      setDropTarget(getDropTarget(event));
    }

    function handlePointerUp(event) {
      const { onMove } = optionsRef.current;
      const target = getDropTarget(event);
      if (target.id) onMove?.(draggingId, target.id, target.placement);
      setDraggingId("");
      setDropTarget({ id: "", placement: "before" });
    }

    window.addEventListener("pointermove", handlePointerMove);
    window.addEventListener("pointerup", handlePointerUp, { once: true });
    window.addEventListener("pointercancel", handlePointerUp, { once: true });
    return () => {
      window.removeEventListener("pointermove", handlePointerMove);
      window.removeEventListener("pointerup", handlePointerUp);
      window.removeEventListener("pointercancel", handlePointerUp);
    };
  }, [draggingId, targetSelector]);

  function startDrag(event, id) {
    if (event.button !== 0) return;
    event.preventDefault();
    event.currentTarget.setPointerCapture?.(event.pointerId);
    setDraggingId(id);
    setDropTarget({ id: "", placement: "before" });
  }

  return { draggingId, dropTarget, startDrag };
}
