import { describe, expect, it, vi } from "vitest";
import { beginAllocationDragSession } from "./timelineAllocationDragSession.js";

describe("timelineAllocationDragSession", () => {
  it("starts the session, forwards movement, and finalizes on mouseup", () => {
    const previousCleanup = vi.fn();
    const setState = vi.fn();
    const updatePosition = vi.fn();
    const finalize = vi.fn();
    const state = { allocationId: "alloc-1", isActive: true };
    const cleanupRef = { current: previousCleanup as (() => void) | null };
    const stateRef = { current: { allocationId: null, isActive: false } };
    const handlers: {
      move?: (event: MouseEvent) => void;
      up?: (event: MouseEvent) => void;
    } = {};

    beginAllocationDragSession({
      state,
      cleanupRef,
      stateRef,
      setState,
      documentTarget: {} as Document,
      attachDrag: (_documentTarget, onMove, onUp) => {
        handlers.move = onMove;
        handlers.up = onUp;
        return vi.fn();
      },
      updatePosition,
      finalize,
    });

    expect(previousCleanup).toHaveBeenCalledOnce();
    expect(stateRef.current).toBe(state);
    expect(setState).toHaveBeenCalledWith(state);

    handlers.move?.({ clientX: 44 } as MouseEvent);
    expect(updatePosition).toHaveBeenCalledWith(44);

    const preventDefault = vi.fn();
    const attachedCleanup = cleanupRef.current;
    handlers.up?.({ clientX: 65, preventDefault } as unknown as MouseEvent);

    expect(attachedCleanup).toHaveBeenCalledOnce();
    expect(cleanupRef.current).toBeNull();
    expect(finalize).toHaveBeenCalledWith(65);
    expect(preventDefault).toHaveBeenCalledOnce();
  });

  it("works when the session starts without a prior cleanup", () => {
    const setState = vi.fn();
    const updatePosition = vi.fn();
    const finalize = vi.fn().mockResolvedValue(undefined);
    const cleanupRef = { current: null as (() => void) | null };
    const stateRef = { current: { allocationId: null, isActive: false } };
    let upHandler: ((event: MouseEvent) => void) | undefined;

    beginAllocationDragSession({
      state: { allocationId: "alloc-2", isActive: true },
      cleanupRef,
      stateRef,
      setState,
      documentTarget: {} as Document,
      attachDrag: (_documentTarget, _onMove, onUp) => {
        upHandler = onUp;
        return vi.fn();
      },
      updatePosition,
      finalize,
    });

    upHandler?.({ clientX: 18, preventDefault() {} } as MouseEvent);

    expect(updatePosition).not.toHaveBeenCalled();
    expect(finalize).toHaveBeenCalledWith(18);
    expect(cleanupRef.current).toBeNull();
  });
});
