import { describe, expect, it } from "vitest";
import { createRangeSelectionState, finalizeRangeSelection, updateRangeSelectionDraft } from "./timelineRangeSelection.js";

type TestRangeState = {
  isSelecting: boolean;
  resourceId: string | null;
  startDate: Date | null;
  currentDate: Date | null;
  suggestedProjectId: string | null;
  startClientX: number;
};

describe("timelineRangeSelection", () => {
  it("creates a selection draft with currentDate anchored to the start date", () => {
    expect(
      createRangeSelectionState<TestRangeState>(
        "res-1",
        new Date("2025-01-15T12:00:00.000Z"),
        100,
      ),
    ).toEqual({
      isSelecting: true,
      resourceId: "res-1",
      startDate: new Date("2025-01-15T12:00:00.000Z"),
      currentDate: new Date("2025-01-15T12:00:00.000Z"),
      suggestedProjectId: null,
      startClientX: 100,
    });
  });

  it("ignores updates when no full day boundary was crossed", () => {
    const state: TestRangeState = {
      isSelecting: true,
      resourceId: "res-1",
      startDate: new Date("2025-01-15T12:00:00.000Z"),
      currentDate: new Date("2025-01-15T12:00:00.000Z"),
      suggestedProjectId: "proj-1",
      startClientX: 100,
    };

    expect(updateRangeSelectionDraft(state, 115, 32)).toBeNull();
  });

  it("updates the preview date when drag distance crosses into another day", () => {
    const state: TestRangeState = {
      isSelecting: true,
      resourceId: "res-1",
      startDate: new Date("2025-01-15T12:00:00.000Z"),
      currentDate: new Date("2025-01-15T12:00:00.000Z"),
      suggestedProjectId: "proj-1",
      startClientX: 100,
    };

    const updated = updateRangeSelectionDraft(state, 168, 32);

    expect(updated).toMatchObject({
      ...state,
      currentDate: new Date("2025-01-17T12:00:00.000Z"),
    });
  });

  it("returns null when finalizing an incomplete range selection", () => {
    expect(
      finalizeRangeSelection(
        {
          isSelecting: true,
          resourceId: null,
          startDate: new Date("2025-01-15T12:00:00.000Z"),
          currentDate: null,
          suggestedProjectId: null,
          startClientX: 100,
        },
        200,
        300,
      ),
    ).toBeNull();
  });

  it("orders the final range chronologically even when the user dragged backwards", () => {
    expect(
      finalizeRangeSelection(
        {
          isSelecting: true,
          resourceId: "res-1",
          startDate: new Date("2025-01-15T12:00:00.000Z"),
          currentDate: new Date("2025-01-12T12:00:00.000Z"),
          suggestedProjectId: "proj-1",
          startClientX: 100,
        },
        200,
        300,
      ),
    ).toEqual({
      resourceId: "res-1",
      startDate: new Date("2025-01-12T12:00:00.000Z"),
      endDate: new Date("2025-01-15T12:00:00.000Z"),
      suggestedProjectId: "proj-1",
      anchorX: 200,
      anchorY: 300,
    });
  });
});
