import { AllocationStatus } from "@capakraken/shared";
import { describe, expect, it } from "vitest";
import { detectOverlaps, validateAvailability } from "../allocation/availability-validator.js";

const stdAvailability = {
  monday: 8,
  tuesday: 8,
  wednesday: 8,
  thursday: 8,
  friday: 8,
};

describe("validateAvailability", () => {
  it("passes when no existing allocations", () => {
    const result = validateAvailability(
      new Date("2025-01-06"),
      new Date("2025-01-10"),
      8,
      stdAvailability,
      [],
    );
    expect(result.valid).toBe(true);
    expect(result.conflicts).toHaveLength(0);
  });

  it("detects conflict when combined hours exceed availability", () => {
    const existing = [{
      startDate: new Date("2025-01-06"),
      endDate: new Date("2025-01-10"),
      hoursPerDay: 6,
      status: AllocationStatus.CONFIRMED,
    }];

    const result = validateAvailability(
      new Date("2025-01-06"),
      new Date("2025-01-10"),
      4, // 6+4=10 > 8
      stdAvailability,
      existing,
    );

    expect(result.valid).toBe(false);
    expect(result.conflicts).toHaveLength(5); // All 5 working days
  });

  it("passes when combined hours exactly match availability", () => {
    const existing = [{
      startDate: new Date("2025-01-06"),
      endDate: new Date("2025-01-10"),
      hoursPerDay: 4,
      status: AllocationStatus.CONFIRMED,
    }];

    const result = validateAvailability(
      new Date("2025-01-06"),
      new Date("2025-01-10"),
      4, // 4+4=8 ≤ 8
      stdAvailability,
      existing,
    );

    expect(result.valid).toBe(true);
  });

  it("ignores cancelled allocations", () => {
    const existing = [{
      startDate: new Date("2025-01-06"),
      endDate: new Date("2025-01-10"),
      hoursPerDay: 8,
      status: AllocationStatus.CANCELLED,
    }];

    const result = validateAvailability(
      new Date("2025-01-06"),
      new Date("2025-01-10"),
      8,
      stdAvailability,
      existing,
    );

    expect(result.valid).toBe(true);
  });

  it("skips non-working days in conflict check", () => {
    const result = validateAvailability(
      new Date("2025-01-04"), // Saturday
      new Date("2025-01-05"), // Sunday
      8,
      stdAvailability,
      [],
    );

    expect(result.valid).toBe(true);
    expect(result.conflicts).toHaveLength(0);
  });
});

describe("detectOverlaps", () => {
  const existingAlloc = {
    id: "alloc-1",
    startDate: new Date("2025-01-06"),
    endDate: new Date("2025-01-10"),
    projectId: "proj-1",
    status: AllocationStatus.ACTIVE,
  };

  it("detects overlapping allocations", () => {
    const overlaps = detectOverlaps(
      new Date("2025-01-08"),
      new Date("2025-01-15"),
      [existingAlloc],
    );
    expect(overlaps).toContain("alloc-1");
  });

  it("returns empty for non-overlapping date ranges", () => {
    const overlaps = detectOverlaps(
      new Date("2025-01-13"), // Starts after existing ends
      new Date("2025-01-17"),
      [existingAlloc],
    );
    expect(overlaps).toHaveLength(0);
  });

  it("excludes same-project allocations when excludeProjectId provided", () => {
    const overlaps = detectOverlaps(
      new Date("2025-01-08"),
      new Date("2025-01-15"),
      [existingAlloc],
      "proj-1", // Exclude this project
    );
    expect(overlaps).toHaveLength(0);
  });

  it("ignores cancelled allocations", () => {
    const cancelled = { ...existingAlloc, status: AllocationStatus.CANCELLED };
    const overlaps = detectOverlaps(
      new Date("2025-01-08"),
      new Date("2025-01-15"),
      [cancelled],
    );
    expect(overlaps).toHaveLength(0);
  });
});
