import { describe, expect, it } from "vitest";
import {
  calculateAllocation,
  calculateTotalCost,
  countWorkingDays,
  isWorkday,
} from "../allocation/calculator.js";

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

describe("isWorkday", () => {
  it("returns true for Monday", () => {
    expect(isWorkday(new Date("2025-01-06"), stdAvailability)).toBe(true); // Monday
  });

  it("returns false for Saturday", () => {
    expect(isWorkday(new Date("2025-01-04"), stdAvailability)).toBe(false); // Saturday
  });

  it("returns false for Sunday", () => {
    expect(isWorkday(new Date("2025-01-05"), stdAvailability)).toBe(false); // Sunday
  });
});

describe("countWorkingDays", () => {
  it("counts 5 days in a Mon-Fri week", () => {
    const start = new Date("2025-01-06"); // Monday
    const end = new Date("2025-01-10"); // Friday
    expect(countWorkingDays(start, end, stdAvailability)).toBe(5);
  });

  it("counts 10 days over two Mon-Fri weeks", () => {
    const start = new Date("2025-01-06"); // Monday
    const end = new Date("2025-01-17"); // Friday
    expect(countWorkingDays(start, end, stdAvailability)).toBe(10);
  });

  it("counts 0 for a weekend-only range", () => {
    const start = new Date("2025-01-04"); // Saturday
    const end = new Date("2025-01-05"); // Sunday
    expect(countWorkingDays(start, end, stdAvailability)).toBe(0);
  });

  it("counts same day as 1 if it's a workday", () => {
    const day = new Date("2025-01-06"); // Monday
    expect(countWorkingDays(day, day, stdAvailability)).toBe(1);
  });
});

describe("calculateAllocation", () => {
  it("calculates cost for a full week at 8h/day and 100 EUR/h (10000 cents)", () => {
    const result = calculateAllocation({
      lcrCents: 10000, // 100 EUR/h
      hoursPerDay: 8,
      startDate: new Date("2025-01-06"), // Monday
      endDate: new Date("2025-01-10"), // Friday
      availability: stdAvailability,
    });

    expect(result.workingDays).toBe(5);
    expect(result.totalHours).toBe(40);
    // 5 days × 8h × 10000 cents/h = 400000 cents = 4000 EUR
    expect(result.totalCostCents).toBe(400000);
    expect(result.dailyCostCents).toBe(80000);
    expect(result.dailyBreakdown).toHaveLength(5);
  });

  it("skips weekend days in breakdown", () => {
    const result = calculateAllocation({
      lcrCents: 10000,
      hoursPerDay: 8,
      startDate: new Date("2025-01-04"), // Saturday
      endDate: new Date("2025-01-12"), // Sunday
      availability: stdAvailability,
    });

    expect(result.workingDays).toBe(5);
    const weekendDays = result.dailyBreakdown.filter((d) => !d.isWorkday);
    expect(weekendDays).toHaveLength(4); // 2 weekends
  });

  it("caps hours at available hours if requested > available", () => {
    const limitedAvailability = { ...stdAvailability, monday: 4 };
    const result = calculateAllocation({
      lcrCents: 10000,
      hoursPerDay: 8, // Requested more than available
      startDate: new Date("2025-01-06"), // Monday only
      endDate: new Date("2025-01-06"),
      availability: limitedAvailability,
    });

    expect(result.totalHours).toBe(4); // Capped at availability
    expect(result.totalCostCents).toBe(40000); // 4h × 10000 cents
  });

  it("returns zero for date range with no working days", () => {
    const result = calculateAllocation({
      lcrCents: 10000,
      hoursPerDay: 8,
      startDate: new Date("2025-01-04"), // Saturday
      endDate: new Date("2025-01-05"), // Sunday
      availability: stdAvailability,
    });

    expect(result.workingDays).toBe(0);
    expect(result.totalHours).toBe(0);
    expect(result.totalCostCents).toBe(0);
  });
});

describe("calculateTotalCost", () => {
  it("calculates correctly", () => {
    // 10000 cents/h × 8h × 5 days = 400000 cents
    expect(calculateTotalCost(10000, 8, 5)).toBe(400000);
  });

  it("returns 0 for 0 working days", () => {
    expect(calculateTotalCost(10000, 8, 0)).toBe(0);
  });
});
