import { describe, expect, it } from "vitest";
import {
  completeMultiSelectDraft,
  createMultiSelectState,
  finalizeMultiSelectDraft,
  updateMultiSelectDraft,
} from "./timelineMultiSelect.js";

type TestMultiSelectState = {
  isSelecting: boolean;
  startX: number;
  startY: number;
  currentX: number;
  currentY: number;
  selectedAllocationIds: string[];
  selectedResourceIds: string[];
  dateRange: { start: Date; end: Date } | null;
  multiDragDaysDelta: number;
  isMultiDragging: boolean;
  multiDragMode: "move" | "resize-start" | "resize-end";
};

describe("timelineMultiSelect", () => {
  it("creates a fresh drag-selection state with the provided origin", () => {
    expect(
      createMultiSelectState<TestMultiSelectState>(120, 240, {
        selectedAllocationIds: [],
        selectedResourceIds: [],
        dateRange: null,
        multiDragDaysDelta: 0,
        isMultiDragging: false,
        multiDragMode: "move",
      }),
    ).toEqual({
      isSelecting: true,
      startX: 120,
      startY: 240,
      currentX: 120,
      currentY: 240,
      selectedAllocationIds: [],
      selectedResourceIds: [],
      dateRange: null,
      multiDragDaysDelta: 0,
      isMultiDragging: false,
      multiDragMode: "move",
    });
  });

  it("updates only the current rectangle coordinates while preserving selection metadata", () => {
    const state = createMultiSelectState<TestMultiSelectState>(120, 240, {
      selectedAllocationIds: ["alloc-1"],
      selectedResourceIds: ["res-1"],
      dateRange: {
        start: new Date("2025-01-01T00:00:00.000Z"),
        end: new Date("2025-01-02T00:00:00.000Z"),
      },
      multiDragDaysDelta: 3,
      isMultiDragging: true,
      multiDragMode: "resize-end",
    });

    expect(updateMultiSelectDraft(state, 155, 275)).toEqual({
      ...state,
      currentX: 155,
      currentY: 275,
    });
  });

  it("resets minimal right-click movement instead of producing a drag rectangle", () => {
    const state = createMultiSelectState<TestMultiSelectState>(120, 240, {
      selectedAllocationIds: [],
      selectedResourceIds: [],
      dateRange: null,
      multiDragDaysDelta: 0,
      isMultiDragging: false,
      multiDragMode: "move",
    });

    expect(finalizeMultiSelectDraft(state, 123, 243)).toBeNull();
  });

  it("finalizes a real drag by freezing the rectangle and clearing only isSelecting", () => {
    const state = createMultiSelectState<TestMultiSelectState>(120, 240, {
      selectedAllocationIds: ["alloc-1"],
      selectedResourceIds: ["res-1"],
      dateRange: {
        start: new Date("2025-01-01T00:00:00.000Z"),
        end: new Date("2025-01-02T00:00:00.000Z"),
      },
      multiDragDaysDelta: 2,
      isMultiDragging: true,
      multiDragMode: "resize-start",
    });

    expect(finalizeMultiSelectDraft(state, 150, 295)).toEqual({
      ...state,
      isSelecting: false,
      currentX: 150,
      currentY: 295,
    });
  });

  it("returns the provided empty state when the right-click drag never really started", () => {
    const state = createMultiSelectState<TestMultiSelectState>(120, 240, {
      selectedAllocationIds: ["alloc-1"],
      selectedResourceIds: ["res-1"],
      dateRange: null,
      multiDragDaysDelta: 1,
      isMultiDragging: true,
      multiDragMode: "move",
    });
    const emptyState: TestMultiSelectState = {
      isSelecting: false,
      startX: 0,
      startY: 0,
      currentX: 0,
      currentY: 0,
      selectedAllocationIds: [],
      selectedResourceIds: [],
      dateRange: null,
      multiDragDaysDelta: 0,
      isMultiDragging: false,
      multiDragMode: "move",
    };

    expect(completeMultiSelectDraft(state, 123, 243, emptyState)).toEqual({
      nextState: emptyState,
      shouldClear: true,
    });
  });

  it("keeps the finished rectangle when the drag cleared the minimum distance", () => {
    const state = createMultiSelectState<TestMultiSelectState>(120, 240, {
      selectedAllocationIds: [],
      selectedResourceIds: [],
      dateRange: null,
      multiDragDaysDelta: 0,
      isMultiDragging: false,
      multiDragMode: "move",
    });
    const emptyState: TestMultiSelectState = {
      isSelecting: false,
      startX: 0,
      startY: 0,
      currentX: 0,
      currentY: 0,
      selectedAllocationIds: [],
      selectedResourceIds: [],
      dateRange: null,
      multiDragDaysDelta: 0,
      isMultiDragging: false,
      multiDragMode: "move",
    };

    expect(completeMultiSelectDraft(state, 150, 295, emptyState)).toEqual({
      nextState: {
        ...state,
        isSelecting: false,
        currentX: 150,
        currentY: 295,
      },
      shouldClear: false,
    });
  });
});
