"use client";

import * as React from "react";
import {
  DndContext,
  PointerSensor,
  TouchSensor,
  KeyboardSensor,
  useSensor,
  useSensors,
  type DragStartEvent,
  type DragEndEvent,
  type DragOverEvent,
  type CollisionDetection,
} from "@dnd-kit/core";
import { sortableKeyboardCoordinates } from "@dnd-kit/sortable";

/** Module scope: each `KanbanBoard` mount gets a unique Dnd session id (avoids key=0 collisions). */
let kanbanDndSessionSeq = 0;

export function nextKanbanDndSessionKey(): number {
  kanbanDndSessionSeq += 1;
  return kanbanDndSessionSeq;
}

/**
 * Keeps `useSensors` and `DndContext` on the same React tree node so remounting the session
 * (via `key` on this component) recreates PointerSensor listeners — fixing stuck drag after
 * list/kanban toggles, route changes, or tab backgrounding.
 */
export function KanbanDndRuntime({
  autoScroll,
  collisionDetection,
  onDragStart,
  onDragOver,
  onDragEnd,
  onDragCancel,
  children,
}: {
  autoScroll: boolean | { enabled: boolean; threshold: { x: number; y: number } };
  collisionDetection: CollisionDetection;
  onDragStart: (event: DragStartEvent) => void;
  onDragOver: (event: DragOverEvent) => void;
  onDragEnd: (event: DragEndEvent) => void;
  onDragCancel: () => void;
  children: React.ReactNode;
}) {
  const sensors = useSensors(
    useSensor(PointerSensor, React.useMemo(() => ({
      activationConstraint: { distance: 8 },
    }), [])),
    useSensor(TouchSensor, React.useMemo(() => ({
      activationConstraint: { delay: 150, tolerance: 8 },
    }), [])),
    useSensor(KeyboardSensor, React.useMemo(() => ({
      coordinateGetter: sortableKeyboardCoordinates,
    }), [])),
  );

  React.useLayoutEffect(() => {
    return () => {
      try {
        document.dispatchEvent(
          new PointerEvent("pointercancel", { bubbles: true, cancelable: true }),
        );
      } catch {
        /* ignore */
      }
    };
  }, []);

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={collisionDetection}
      onDragStart={onDragStart}
      onDragOver={onDragOver}
      onDragEnd={onDragEnd}
      onDragCancel={onDragCancel}
      autoScroll={autoScroll}
    >
      {children}
    </DndContext>
  );
}
