import { describe, expect, it, vi } from "vitest";
import { SystemRole } from "@capakraken/shared";

vi.mock("@capakraken/application", async (importOriginal) => {
  const actual = await importOriginal<typeof import("@capakraken/application")>();
  return {
    ...actual,
    getDashboardBudgetForecast: vi.fn().mockResolvedValue([]),
    listAssignmentBookings: vi.fn().mockResolvedValue([]),
  };
});

vi.mock("../lib/audit.js", () => ({
  createAuditEntry: vi.fn().mockResolvedValue(undefined),
}));

import { executeTool, type ToolContext } from "../router/assistant-tools.js";

function createToolContext(
  db: Record<string, unknown>,
  permissions: string[] = [],
  userRole: SystemRole = SystemRole.ADMIN,
): ToolContext {
  return {
    db: db as ToolContext["db"],
    userId: "user_1",
    userRole,
    permissions: new Set(permissions) as ToolContext["permissions"],
    session: {
      user: { email: "assistant@example.com", name: "Assistant User", image: null },
      expires: "2026-03-29T00:00:00.000Z",
    },
    dbUser: {
      id: "user_1",
      systemRole: userRole,
      permissionOverrides: null,
    },
    roleDefaults: null,
  };
}

describe("assistant holiday tools", () => {
  it("lists regional holidays and distinguishes Bavaria from Hamburg", async () => {
    const ctx = createToolContext({});

    const bavaria = await executeTool(
      "list_holidays_by_region",
      JSON.stringify({ countryCode: "DE", federalState: "BY", year: 2026 }),
      ctx,
    );
    const hamburg = await executeTool(
      "list_holidays_by_region",
      JSON.stringify({ countryCode: "DE", federalState: "HH", year: 2026 }),
      ctx,
    );

    const bavariaResult = JSON.parse(bavaria.content) as {
      count: number;
      locationContext: { federalState: string | null };
      summary: { byScope: Array<{ scope: string; count: number }> };
      holidays: Array<{ name: string; date: string }>;
    };
    const hamburgResult = JSON.parse(hamburg.content) as {
      count: number;
      locationContext: { federalState: string | null };
      holidays: Array<{ name: string; date: string }>;
    };

    expect(bavariaResult.count).toBeGreaterThan(hamburgResult.count);
    expect(bavariaResult.locationContext.federalState).toBe("BY");
    expect(bavariaResult.summary.byScope).toEqual(
      expect.arrayContaining([expect.objectContaining({ scope: "STATE" })]),
    );
    expect(bavariaResult.holidays).toEqual(
      expect.arrayContaining([
        expect.objectContaining({ name: "Heilige Drei Könige", date: "2026-01-06" }),
      ]),
    );
    expect(hamburgResult.holidays).not.toEqual(
      expect.arrayContaining([
        expect.objectContaining({ name: "Heilige Drei Könige", date: "2026-01-06" }),
      ]),
    );
  });

  it("resolves resource-specific holidays including city-local dates", async () => {
    const db = {
      resource: {
        findUnique: vi
          .fn()
          .mockResolvedValueOnce(null)
          .mockResolvedValueOnce({ id: "res_1", eid: "bruce.banner", displayName: "Bruce Banner" })
          .mockResolvedValueOnce({ id: "res_1", eid: "bruce.banner", displayName: "Bruce Banner", federalState: "BY", countryId: "country_de", metroCityId: "city_augsburg", country: { code: "DE", name: "Deutschland" }, metroCity: { name: "Augsburg" } }),
        findFirst: vi.fn(),
      },
    };
    const ctx = createToolContext(db);

    const result = await executeTool(
      "get_resource_holidays",
      JSON.stringify({ identifier: "bruce.banner", year: 2026 }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      resource: { eid: string; federalState: string | null; metroCity: string | null };
      summary: { byScope: Array<{ scope: string; count: number }> };
      holidays: Array<{ name: string; date: string }>;
    };

    expect(parsed.resource).toEqual(
      expect.objectContaining({
        eid: "bruce.banner",
        federalState: "BY",
        metroCity: "Augsburg",
      }),
    );
    expect(parsed.holidays).toEqual(
      expect.arrayContaining([
        expect.objectContaining({ name: "Augsburger Friedensfest", date: "2026-08-08" }),
      ]),
    );
    expect(parsed.summary.byScope).toEqual(
      expect.arrayContaining([expect.objectContaining({ scope: "CITY" })]),
    );
  });

  it("lists holiday calendars with scope metadata and entry counts", async () => {
    const ctx = createToolContext({
      holidayCalendar: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "cal_by",
            name: "Bayern Feiertage",
            scopeType: "STATE",
            stateCode: "BY",
            isActive: true,
            priority: 10,
            country: { id: "country_de", code: "DE", name: "Deutschland" },
            metroCity: null,
            _count: { entries: 2 },
            entries: [
              {
                id: "entry_1",
                date: new Date("2026-01-06T00:00:00.000Z"),
                name: "Heilige Drei Koenige",
                isRecurringAnnual: true,
                source: "state",
              },
            ],
          },
        ]),
      },
    });

    const result = await executeTool(
      "list_holiday_calendars",
      JSON.stringify({ countryCode: "DE", scopeType: "STATE", includeInactive: true }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      count: number;
      calendars: Array<{
        name: string;
        scopeType: string;
        stateCode: string | null;
        entryCount: number;
        country: { code: string };
      }>;
    };

    expect(parsed.count).toBe(1);
    expect(parsed.calendars).toHaveLength(1);
    expect(parsed.calendars[0]).toMatchObject({
      name: "Bayern Feiertage",
      scopeType: "STATE",
      stateCode: "BY",
      entryCount: 2,
      country: { code: "DE" },
    });
  });

  it("previews resolved holiday calendars for a scope and shows the source calendar", async () => {
    const ctx = createToolContext({
      country: {
        findUnique: vi.fn().mockResolvedValue({ id: "country_de", code: "DE", name: "Deutschland" }),
      },
      metroCity: {
        findUnique: vi.fn().mockResolvedValue({ id: "city_augsburg", name: "Augsburg", countryId: "country_de" }),
      },
      holidayCalendar: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "cal_city",
            name: "Augsburg lokal",
            scopeType: "CITY",
            priority: 5,
            createdAt: new Date("2026-01-01T00:00:00.000Z"),
            entries: [
              {
                id: "entry_1",
                date: new Date("2020-08-08T00:00:00.000Z"),
                name: "Friedensfest lokal",
                isRecurringAnnual: true,
                source: "manual",
              },
            ],
          },
        ]),
      },
    });

    const result = await executeTool(
      "preview_resolved_holiday_calendar",
      JSON.stringify({ countryId: "country_de", metroCityId: "city_augsburg", year: 2026 }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      count: number;
      locationContext: { countryCode: string; metroCity: string | null; year: number };
      holidays: Array<{ name: string; calendarName: string; scope: string; date: string }>;
    };

    expect(parsed.count).toBeGreaterThan(0);
    expect(parsed.locationContext).toEqual(
      expect.objectContaining({
        countryCode: "DE",
        metroCity: "Augsburg",
        year: 2026,
      }),
    );
    expect(parsed.holidays).toEqual(
      expect.arrayContaining([
        expect.objectContaining({
          name: "Friedensfest lokal",
          calendarName: "Augsburg lokal",
          scope: "CITY",
          date: "2026-08-08",
        }),
      ]),
    );
    expect(ctx.db.country.findUnique).toHaveBeenCalledWith({
      where: { id: "country_de" },
      select: { id: true, code: true, name: true },
    });
    expect(ctx.db.metroCity.findUnique).toHaveBeenCalledWith({
      where: { id: "city_augsburg" },
      select: { id: true, name: true, countryId: true },
    });
  });

  it("creates a holiday calendar through the assistant for admin users", async () => {
    const ctx = createToolContext({
      country: {
        findUnique: vi.fn().mockResolvedValue({ id: "country_de", code: "DE", name: "Deutschland" }),
      },
      holidayCalendar: {
        findFirst: vi.fn().mockResolvedValue(null),
        create: vi.fn().mockResolvedValue({
          id: "cal_by",
          name: "Bayern Feiertage",
          scopeType: "STATE",
          stateCode: "BY",
          isActive: true,
          priority: 10,
          country: { id: "country_de", code: "DE", name: "Deutschland" },
          metroCity: null,
          entries: [],
        }),
      },
    });

    const result = await executeTool(
      "create_holiday_calendar",
      JSON.stringify({
        name: "Bayern Feiertage",
        scopeType: "STATE",
        countryId: "country_de",
        stateCode: "BY",
        priority: 10,
      }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      success: boolean;
      message: string;
      calendar: { name: string; stateCode: string | null };
    };

    expect(parsed.success).toBe(true);
    expect(parsed.message).toContain("Created holiday calendar");
    expect(parsed.calendar).toEqual(
      expect.objectContaining({
        name: "Bayern Feiertage",
        stateCode: "BY",
      }),
    );
  });

  it("rejects holiday calendar mutations for non-admin assistant users", async () => {
    const ctx = createToolContext({}, [], SystemRole.MANAGER);
    const result = await executeTool(
      "create_holiday_calendar",
      JSON.stringify({
        name: "Hamburg Feiertage",
        scopeType: "STATE",
        countryId: "country_de",
        stateCode: "HH",
      }),
      ctx,
    );

    expect(JSON.parse(result.content)).toEqual(
      expect.objectContaining({
        error: "Admin role required to perform this action.",
      }),
    );
  });

  it("calculates chargeability with regional holidays excluded from booked and available hours", async () => {
    const resourceRecord = {
      id: "res_1",
      displayName: "Bruce Banner",
      eid: "bruce.banner",
      fte: 1,
      lcrCents: 5000,
      chargeabilityTarget: 80,
      availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8, saturday: 0, sunday: 0 },
      countryId: "country_de",
      federalState: "BY",
      metroCityId: null,
      country: { id: "country_de", code: "DE", name: "Deutschland", dailyWorkingHours: 8, scheduleRules: null },
      metroCity: null,
      managementLevelGroup: null,
    };
    const db = {
      resource: {
        findUnique: vi
          .fn()
          .mockResolvedValueOnce(resourceRecord),
        findUniqueOrThrow: vi.fn().mockResolvedValue(resourceRecord),
        findFirst: vi.fn(),
      },
      assignment: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "assign_1",
            hoursPerDay: 8,
            startDate: new Date("2026-01-05T00:00:00.000Z"),
            endDate: new Date("2026-01-06T00:00:00.000Z"),
            dailyCostCents: 40000,
            status: "CONFIRMED",
            project: {
              id: "project_gamma",
              name: "Gamma",
              shortCode: "GAM",
              budgetCents: null,
              winProbability: 100,
              utilizationCategory: { code: "Chg" },
            },
          },
        ]),
      },
      vacation: {
        findMany: vi.fn().mockResolvedValue([]),
      },
      holidayCalendar: {
        findMany: vi.fn().mockResolvedValue([]),
      },
      calculationRule: {
        findMany: vi.fn().mockResolvedValue([]),
      },
    };
    const ctx = createToolContext(db);

    const result = await executeTool(
      "get_chargeability",
      JSON.stringify({ resourceId: "res_1", month: "2026-01" }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      baseWorkingDays: number;
      baseAvailableHours: number;
      availableHours: number;
      bookedHours: number;
      workingDays: number;
      targetHours: number;
      unassignedHours: number;
      holidaySummary: { count: number; workdayCount: number; hoursDeduction: number };
      capacityBreakdown: { formula: string; holidayHoursDeduction: number; absenceHoursDeduction: number };
      locationContext: { federalState: string | null };
      allocations: Array<{ hours: number }>;
    };

    expect(parsed.bookedHours).toBe(8);
    expect(parsed.allocations).toEqual([expect.objectContaining({ hours: 8 })]);
    expect(parsed.baseWorkingDays).toBe(22);
    expect(parsed.baseAvailableHours).toBe(176);
    expect(parsed.availableHours).toBe(160);
    expect(parsed.workingDays).toBe(20);
    expect(parsed.targetHours).toBe(128);
    expect(parsed.unassignedHours).toBe(152);
    expect(parsed.locationContext.federalState).toBe("BY");
    expect(parsed.holidaySummary).toEqual(
      expect.objectContaining({
        count: 2,
        workdayCount: 2,
        hoursDeduction: 16,
      }),
    );
    expect(parsed.capacityBreakdown).toEqual(
      expect.objectContaining({
        formula: "baseAvailableHours - holidayHoursDeduction - absenceHoursDeduction = availableHours",
        holidayHoursDeduction: 16,
        absenceHoursDeduction: 0,
      }),
    );
  });

  it("returns holiday-aware budget forecast data from the dashboard use-case", async () => {
    const { getDashboardBudgetForecast } = await import("@capakraken/application");
    vi.mocked(getDashboardBudgetForecast).mockResolvedValue([
      {
        projectId: "project_1",
        projectName: "Gelddruckmaschine",
        shortCode: "GDM",
        budgetCents: 100_000,
        spentCents: 60_000,
        burnRate: 5_000,
        pctUsed: 60,
        estimatedExhaustionDate: "2026-02-20",
      },
    ]);

    const ctx = createToolContext({}, ["viewCosts"]);
    const result = await executeTool("get_budget_forecast", "{}", ctx);
    const parsed = JSON.parse(result.content) as {
      forecasts: Array<{
        projectName: string;
        shortCode: string;
        budgetCents: number;
        spentCents: number;
        remainingCents: number;
        projectedCents: number;
        burnRateCents: number;
        burnStatus: string;
      }>;
    };

    expect(parsed.forecasts).toEqual([
      expect.objectContaining({
        projectName: "Gelddruckmaschine",
        shortCode: "GDM",
        budgetCents: 100_000,
        spentCents: 60_000,
        remainingCents: 40_000,
        projectedCents: 100_000,
        burnRateCents: 5_000,
        burnStatus: "on_track",
      }),
    ]);
  });

  it("checks resource availability with regional holidays excluded from capacity", async () => {
    const resourceRecord = {
      id: "res_1",
      displayName: "Bruce Banner",
      eid: "bruce.banner",
      fte: 1,
      availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8, saturday: 0, sunday: 0 },
      countryId: "country_de",
      federalState: "BY",
      metroCityId: null,
      country: { code: "DE", dailyWorkingHours: 8 },
      metroCity: null,
    };
    const db = {
      resource: {
        findUnique: vi
          .fn()
          .mockResolvedValue(resourceRecord),
        findFirst: vi.fn(),
      },
      assignment: {
        findMany: vi.fn().mockResolvedValue([
          {
            hoursPerDay: 8,
            startDate: new Date("2026-01-05T00:00:00.000Z"),
            endDate: new Date("2026-01-06T00:00:00.000Z"),
            status: "CONFIRMED",
            project: { name: "Gamma", shortCode: "GAM" },
          },
        ]),
      },
      vacation: {
        findMany: vi.fn().mockResolvedValue([]),
      },
    };
    const ctx = createToolContext(db);

    const result = await executeTool(
      "check_resource_availability",
      JSON.stringify({ resourceId: "res_1", startDate: "2026-01-05", endDate: "2026-01-06" }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      workingDays: number;
      periodAvailableHours: number;
      periodBookedHours: number;
      periodRemainingHours: number;
      availableHoursPerDay: number;
      isFullyAvailable: boolean;
    };

    expect(parsed.workingDays).toBe(1);
    expect(parsed.periodAvailableHours).toBe(8);
    expect(parsed.periodBookedHours).toBe(8);
    expect(parsed.periodRemainingHours).toBe(0);
    expect(parsed.availableHoursPerDay).toBe(0);
    expect(parsed.isFullyAvailable).toBe(false);
  });

  it("keeps scenario simulation flat when a proposed change falls on a local holiday", async () => {
    const db = {
      project: {
        findUnique: vi.fn().mockResolvedValue({
          id: "project_1",
          name: "Holiday Project",
          budgetCents: 500_000,
          startDate: new Date("2026-01-01T00:00:00.000Z"),
          endDate: new Date("2026-01-31T00:00:00.000Z"),
        }),
      },
      assignment: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "assignment_1",
            resourceId: "res_1",
            hoursPerDay: 8,
            startDate: new Date("2026-01-05T00:00:00.000Z"),
            endDate: new Date("2026-01-05T00:00:00.000Z"),
            status: "CONFIRMED",
            resource: {
              id: "res_1",
              displayName: "Bruce Banner",
              lcrCents: 100,
              availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
              chargeabilityTarget: 80,
              countryId: "country_de",
              federalState: "BY",
              metroCityId: null,
              country: { code: "DE", dailyWorkingHours: 8 },
              metroCity: null,
            },
          },
        ]),
      },
      resource: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "res_1",
            displayName: "Bruce Banner",
            lcrCents: 100,
            availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
            chargeabilityTarget: 80,
            countryId: "country_de",
            federalState: "BY",
            metroCityId: null,
            country: { code: "DE", dailyWorkingHours: 8 },
            metroCity: null,
          },
        ]),
      },
    };
    const ctx = createToolContext(db, ["manageAllocations"]);

    const result = await executeTool(
      "simulate_scenario",
      JSON.stringify({
        projectId: "project_1",
        changes: [
          {
            resourceId: "res_1",
            startDate: "2026-01-06",
            endDate: "2026-01-06",
            hoursPerDay: 8,
          },
        ],
      }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      baseline: { totalHours: number; totalCostCents: number };
      scenario: { totalHours: number; totalCostCents: number };
      delta: { hours: number; costCents: number };
    };

    expect(parsed.baseline).toEqual(
      expect.objectContaining({
        totalHours: 8,
        totalCostCents: 800,
      }),
    );
    expect(parsed.scenario).toEqual(
      expect.objectContaining({
        totalHours: 8,
        totalCostCents: 800,
      }),
    );
    expect(parsed.delta).toEqual(
      expect.objectContaining({
        hours: 0,
        costCents: 0,
      }),
    );
  });

  it("prefers resources without a local holiday in staffing suggestions", async () => {
    const db = {
      project: {
        findUnique: vi.fn().mockResolvedValue({
          id: "project_1",
          name: "Holiday Project",
          shortCode: "HP",
          startDate: new Date("2026-01-06T00:00:00.000Z"),
          endDate: new Date("2026-01-06T00:00:00.000Z"),
        }),
        findFirst: vi.fn().mockResolvedValue(null),
      },
      assignment: {
        findMany: vi.fn().mockResolvedValue([]),
      },
      resource: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "res_by",
            displayName: "Bavaria",
            eid: "BY-1",
            fte: 1,
            lcrCents: 10000,
            chargeabilityTarget: 80,
            valueScore: 10,
            skills: [],
            availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
            countryId: "country_de",
            federalState: "BY",
            metroCityId: null,
            country: { code: "DE", name: "Deutschland" },
            metroCity: null,
            areaRole: { name: "Consultant" },
            chapter: "CGI",
          },
          {
            id: "res_hh",
            displayName: "Hamburg",
            eid: "HH-1",
            fte: 1,
            lcrCents: 10000,
            chargeabilityTarget: 80,
            valueScore: 10,
            skills: [],
            availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
            countryId: "country_de",
            federalState: "HH",
            metroCityId: null,
            country: { code: "DE", name: "Deutschland" },
            metroCity: null,
            areaRole: { name: "Consultant" },
            chapter: "CGI",
          },
        ]),
      },
    };
    const ctx = createToolContext(db);

    const result = await executeTool(
      "get_staffing_suggestions",
      JSON.stringify({ projectId: "project_1", limit: 5 }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      suggestions: Array<{ name: string; availableHours: number }>;
    };

    expect(parsed.suggestions).toHaveLength(1);
    expect(parsed.suggestions[0]).toEqual(
      expect.objectContaining({ name: "Hamburg", availableHours: 8 }),
    );
    expect(db.project.findUnique).toHaveBeenCalledWith({
      where: { id: "project_1" },
      select: expect.objectContaining({
        id: true,
        shortCode: true,
        name: true,
        startDate: true,
        endDate: true,
      }),
    });
  });

  it("finds capacity with local holidays respected", async () => {
    const db = {
      resource: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "res_by",
            displayName: "Bavaria",
            eid: "BY-1",
            fte: 1,
            availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
            countryId: "country_de",
            federalState: "BY",
            metroCityId: null,
            country: { code: "DE" },
            metroCity: null,
            areaRole: { name: "Consultant" },
            chapter: "CGI",
            assignments: [],
          },
          {
            id: "res_hh",
            displayName: "Hamburg",
            eid: "HH-1",
            fte: 1,
            availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
            countryId: "country_de",
            federalState: "HH",
            metroCityId: null,
            country: { code: "DE" },
            metroCity: null,
            areaRole: { name: "Consultant" },
            chapter: "CGI",
            assignments: [],
          },
        ]),
      },
      vacation: {
        findMany: vi.fn().mockResolvedValue([]),
      },
    };
    const ctx = createToolContext(db);

    const result = await executeTool(
      "find_capacity",
      JSON.stringify({ startDate: "2026-01-06", endDate: "2026-01-06", minHoursPerDay: 1 }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      results: Array<{ name: string; availableHours: number; availableHoursPerDay: number }>;
    };

    expect(parsed.results).toHaveLength(1);
    expect(parsed.results[0]).toEqual(
      expect.objectContaining({ name: "Hamburg", availableHours: 8, availableHoursPerDay: 8 }),
    );
  });

  it("uses holiday-aware assignment hours for assistant shoring ratio", async () => {
    const db = {
      project: {
        findUnique: vi
          .fn()
          .mockResolvedValueOnce({
            id: "project_1",
            name: "Holiday Project",
            shortCode: "HP",
            status: "ACTIVE",
            responsiblePerson: null,
          })
          .mockResolvedValueOnce({
            id: "project_1",
            name: "Holiday Project",
            shoringThreshold: 55,
            onshoreCountryCode: "DE",
          }),
      },
      assignment: {
        findMany: vi.fn().mockResolvedValue([
          {
            resourceId: "res_by",
            hoursPerDay: 8,
            startDate: new Date("2026-01-06T00:00:00.000Z"),
            endDate: new Date("2026-01-06T00:00:00.000Z"),
            resource: {
              id: "res_by",
              availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
              countryId: "country_de",
              federalState: "BY",
              metroCityId: null,
              country: { code: "DE" },
              metroCity: null,
            },
          },
          {
            resourceId: "res_in",
            hoursPerDay: 8,
            startDate: new Date("2026-01-06T00:00:00.000Z"),
            endDate: new Date("2026-01-06T00:00:00.000Z"),
            resource: {
              id: "res_in",
              availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
              countryId: "country_in",
              federalState: null,
              metroCityId: null,
              country: { code: "IN" },
              metroCity: null,
            },
          },
        ]),
      },
      vacation: {
        findMany: vi.fn().mockResolvedValue([]),
      },
    };
    const ctx = createToolContext(db);

    const result = await executeTool(
      "get_shoring_ratio",
      JSON.stringify({ projectId: "project_1" }),
      ctx,
    );

    expect(result.content).toContain("0% onshore (DE), 100% offshore");
    expect(result.content).toContain("IN 100% (1 people)");
  });

  it("routes pending vacation approvals through the vacation router path", async () => {
    const db = {
      vacation: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "vac_1",
            type: "ANNUAL",
            startDate: new Date("2026-07-01T00:00:00.000Z"),
            endDate: new Date("2026-07-03T00:00:00.000Z"),
            isHalfDay: false,
            resource: { displayName: "Bruce Banner", eid: "BB-1", chapter: "CGI" },
            requestedBy: { id: "user_2", name: "Manager", email: "manager@example.com" },
          },
        ]),
      },
    };
    const ctx = createToolContext(db, [], SystemRole.MANAGER);

    const result = await executeTool(
      "get_pending_vacation_approvals",
      JSON.stringify({ limit: 10 }),
      ctx,
    );

    expect(db.vacation.findMany).toHaveBeenCalledWith({
      where: { status: "PENDING" },
      include: {
        resource: { select: expect.any(Object) },
        requestedBy: { select: { id: true, name: true, email: true } },
      },
      orderBy: { startDate: "asc" },
    });
    expect(JSON.parse(result.content)).toEqual([
      expect.objectContaining({
        id: "vac_1",
        resource: "Bruce Banner",
        eid: "BB-1",
        chapter: "CGI",
      }),
    ]);
  });

  it("routes team vacation overlap through the vacation router path", async () => {
    const db = {
      resource: {
        findUnique: vi
          .fn()
          .mockResolvedValue({
            id: "res_1",
            displayName: "Bruce Banner",
            eid: "BB-1",
            chapter: "CGI",
            lcrCents: 0,
            isActive: true,
            countryId: null,
            federalState: null,
            metroCityId: null,
            areaRole: null,
            country: null,
            metroCity: null,
          }),
        findFirst: vi.fn(),
        findMany: vi.fn(),
      },
      vacation: {
        findMany: vi.fn().mockResolvedValue([
          {
            type: "ANNUAL",
            status: "APPROVED",
            startDate: new Date("2026-08-10T00:00:00.000Z"),
            endDate: new Date("2026-08-12T00:00:00.000Z"),
            resource: { displayName: "Clark Kent" },
          },
        ]),
      },
    };
    const ctx = createToolContext(db);

    const result = await executeTool(
      "get_team_vacation_overlap",
      JSON.stringify({
        resourceId: "res_1",
        startDate: "2026-08-10",
        endDate: "2026-08-12",
      }),
      ctx,
    );

    expect(db.vacation.findMany).toHaveBeenCalledWith({
      where: {
        resource: { chapter: "CGI" },
        resourceId: { not: "res_1" },
        status: { in: ["APPROVED", "PENDING"] },
        startDate: { lte: new Date("2026-08-12T00:00:00.000Z") },
        endDate: { gte: new Date("2026-08-10T00:00:00.000Z") },
      },
      include: {
        resource: { select: expect.any(Object) },
      },
      orderBy: { startDate: "asc" },
      take: 20,
    });
    expect(JSON.parse(result.content)).toEqual(
      expect.objectContaining({
        resource: "Bruce Banner",
        chapter: "CGI",
        overlapCount: 1,
        overlappingVacations: [
          expect.objectContaining({
            resource: "Clark Kent",
            status: "APPROVED",
          }),
        ],
      }),
    );
  });
});
