import { describe, it, expect } from "vitest";
import { calculateShoringRatio, type ShoringAssignment } from "../allocation/shoring-ratio.js";

function make(resourceId: string, countryCode: string | null, hoursPerDay = 8, workingDays = 20): ShoringAssignment {
  return { resourceId, countryCode, hoursPerDay, workingDays };
}

describe("calculateShoringRatio", () => {
  it("returns zeros for empty assignments", () => {
    const r = calculateShoringRatio([]);
    expect(r.totalHours).toBe(0);
    expect(r.offshoreRatio).toBe(0);
    expect(r.isAboveThreshold).toBe(false);
  });

  it("100% German → 0% offshore", () => {
    const r = calculateShoringRatio([make("r1", "DE"), make("r2", "DE")]);
    expect(r.onshoreRatio).toBe(100);
    expect(r.offshoreRatio).toBe(0);
    expect(r.isAboveThreshold).toBe(false);
  });

  it("100% offshore → 100% offshore, above threshold", () => {
    const r = calculateShoringRatio([make("r1", "ES"), make("r2", "IN")]);
    expect(r.offshoreRatio).toBe(100);
    expect(r.isAboveThreshold).toBe(true);
  });

  it("50/50 mix → 50% offshore, below 55% threshold", () => {
    const r = calculateShoringRatio([make("r1", "DE"), make("r2", "ES")]);
    expect(r.offshoreRatio).toBe(50);
    expect(r.isAboveThreshold).toBe(false);
  });

  it("40% onshore / 60% offshore → above 55% threshold", () => {
    const assignments = [
      make("r1", "DE", 8, 20),  // 160h
      make("r2", "DE", 8, 20),  // 160h  → 320h onshore
      make("r3", "ES", 8, 20),  // 160h
      make("r4", "IN", 8, 20),  // 160h
      make("r5", "IN", 8, 20),  // 160h  → 480h offshore
    ];
    const r = calculateShoringRatio(assignments);
    expect(r.offshoreRatio).toBe(60);
    expect(r.isAboveThreshold).toBe(true);
  });

  it("custom threshold: 30% → 40% offshore is above", () => {
    const assignments = [
      make("r1", "DE", 8, 20),  // 160h onshore
      make("r2", "DE", 8, 20),  // 160h onshore  → 320h
      make("r3", "ES", 4, 20),  // 80h offshore
      make("r4", "IN", 4, 20),  // 80h offshore  → 160h
    ];
    // Total 480h, offshore 160h = 33%
    const r = calculateShoringRatio(assignments, 30);
    expect(r.offshoreRatio).toBe(33);
    expect(r.isAboveThreshold).toBe(true);
  });

  it("resource without country counts as offshore", () => {
    const r = calculateShoringRatio([make("r1", "DE"), make("r2", null)]);
    expect(r.offshoreRatio).toBe(50);
    expect(r.unknownCount).toBe(1);
    expect(r.byCountry["UNKNOWN"]).toBeDefined();
  });

  it("country code is case-insensitive", () => {
    const r = calculateShoringRatio([make("r1", "de"), make("r2", "De")]);
    expect(r.onshoreRatio).toBe(100);
    expect(r.offshoreRatio).toBe(0);
  });

  it("custom onshore country code", () => {
    const r = calculateShoringRatio([make("r1", "ES"), make("r2", "DE")], 55, "ES");
    expect(r.onshoreCountryCode).toBe("ES");
    expect(r.onshoreHours).toBe(160); // r1 is onshore
    expect(r.offshoreHours).toBe(160); // r2 is offshore (DE is not onshore here)
  });

  it("byCountry breakdown is correct", () => {
    const r = calculateShoringRatio([
      make("r1", "DE", 8, 10),
      make("r2", "ES", 8, 10),
      make("r3", "ES", 4, 10),
      make("r4", "IN", 8, 10),
    ]);
    expect(r.byCountry["DE"]!.resourceCount).toBe(1);
    expect(r.byCountry["ES"]!.resourceCount).toBe(2);
    expect(r.byCountry["IN"]!.resourceCount).toBe(1);
    expect(r.byCountry["DE"]!.hours).toBe(80);
    expect(r.byCountry["ES"]!.hours).toBe(120);
    expect(r.byCountry["IN"]!.hours).toBe(80);
  });

  it("exactly at threshold is above", () => {
    // 55% offshore = at threshold = isAboveThreshold true (>= not >)
    // Need 55/100 = 11/20 ratio
    const assignments = [
      make("r1", "DE", 9, 20),   // 180h onshore
      make("r2", "ES", 11, 20),  // 220h offshore
    ];
    // Total 400h, offshore 220h = 55%
    const r = calculateShoringRatio(assignments);
    expect(r.offshoreRatio).toBe(55);
    expect(r.isAboveThreshold).toBe(true);
  });

  it("weighted by hours — FTE matters", () => {
    const r = calculateShoringRatio([
      make("r1", "DE", 8, 20),  // 160h full-time onshore
      make("r2", "ES", 2, 20),  // 40h part-time offshore
    ]);
    // Total 200h, offshore 40h = 20%
    expect(r.offshoreRatio).toBe(20);
    expect(r.isAboveThreshold).toBe(false);
  });
});
