import { beforeEach, describe, expect, it, vi } from "vitest";

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 { getDashboardBudgetForecast } from "@capakraken/application";
import { executeTool } from "../router/assistant-tools.js";
import { createToolContext } from "./assistant-tools-holiday-capacity-test-helpers.js";

describe("assistant holiday-aware budget and shoring tools", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.mocked(getDashboardBudgetForecast).mockResolvedValue([]);
  });

  it("returns holiday-aware budget forecast data from the dashboard use-case", async () => {
    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",
        derivation: {
          periodStart: "2026-02-01",
          periodEnd: "2026-02-28",
          calendarContextCount: 1,
          holidayAwareAssignmentCount: 1,
          fallbackAssignmentCount: 0,
          baseBurnRateCents: 6_000,
          adjustedBurnRateCents: 5_000,
          publicHolidayDayEquivalent: 1,
          publicHolidayCostDeductionCents: 1_000,
          absenceDayEquivalent: 0,
          absenceCostDeductionCents: 0,
        },
      },
    ]);

    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;
        derivation: {
          baseBurnRateCents: number;
          adjustedBurnRateCents: number;
          publicHolidayCostDeductionCents: number;
        } | null;
      }>;
    };

    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,
        derivation: expect.objectContaining({
          baseBurnRateCents: 6_000,
          adjustedBurnRateCents: 5_000,
          publicHolidayCostDeductionCents: 1_000,
        }),
        burnStatus: "on_track",
      }),
    ]);
  });

  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)");
  });
});
