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

vi.mock("@capakraken/application", async (importOriginal) => {
  const actual = await importOriginal<typeof import("@capakraken/application")>();
  return {
    ...actual,
    approveEstimateVersion: vi.fn(),
    cloneEstimate: vi.fn(),
    commitDispoImportBatch: vi.fn(),
    countPlanningEntries: vi.fn().mockResolvedValue({ countsByRoleId: new Map() }),
    createEstimateExport: vi.fn(),
    createEstimatePlanningHandoff: vi.fn(),
    createEstimateRevision: vi.fn(),
    assessDispoImportReadiness: vi.fn(),
    loadResourceDailyAvailabilityContexts: vi.fn().mockResolvedValue(new Map()),
    getDashboardDemand: vi.fn().mockResolvedValue([]),
    getDashboardBudgetForecast: vi.fn().mockResolvedValue([]),
    getDashboardOverview: vi.fn(),
    getDashboardSkillGapSummary: vi.fn().mockResolvedValue({
      roleGaps: [],
      totalOpenPositions: 0,
      skillSupplyTop10: [],
      resourcesByRole: [],
    }),
    getDashboardProjectHealth: vi.fn().mockResolvedValue([]),
    getDashboardPeakTimes: vi.fn().mockResolvedValue([]),
    getDashboardTopValueResources: vi.fn().mockResolvedValue([]),
    getEstimateById: vi.fn(),
    listAssignmentBookings: vi.fn().mockResolvedValue([]),
    stageDispoImportBatch: vi.fn(),
    submitEstimateVersion: vi.fn(),
    updateEstimateDraft: vi.fn(),
  };
});

import { executeTool } from "../router/assistant-tools.js";
import { createToolContext } from "./assistant-tools-vacation-entitlement-test-helpers.js";

describe("assistant vacation balance tools", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("routes vacation balance through the real vacation workflow", async () => {
    const vacationFindMany = vi.fn().mockImplementation(async (args?: any) => {
      if (args?.where?.type === VacationType.PUBLIC_HOLIDAY) {
        return [];
      }
          if (args?.where?.type?.in) {
            return [
              {
                type: VacationType.ANNUAL,
                startDate: new Date("2026-01-05T00:00:00.000Z"),
                endDate: new Date("2026-01-06T00:00:00.000Z"),
                status: "APPROVED",
                isHalfDay: false,
              },
              {
                type: VacationType.ANNUAL,
                startDate: new Date("2026-02-03T00:00:00.000Z"),
                endDate: new Date("2026-02-03T00:00:00.000Z"),
                status: "PENDING",
                isHalfDay: true,
          },
        ];
      }
      if (args?.where?.type === VacationType.SICK) {
        return [
          {
            startDate: new Date("2026-03-10T00:00:00.000Z"),
            endDate: new Date("2026-03-10T00:00:00.000Z"),
            isHalfDay: false,
          },
        ];
      }
      return [];
    });
    const ctx = createToolContext({
      resource: {
        findUnique: vi.fn().mockResolvedValue({
          id: "res_1",
          eid: "EMP-001",
          displayName: "Alice Example",
          userId: "user_1",
          chapter: "Delivery",
          federalState: "BY",
          countryId: "country_de",
          metroCityId: null,
          country: { code: "DE", name: "Germany" },
          metroCity: null,
        }),
      },
      holidayCalendar: {
        findMany: vi.fn().mockResolvedValue([]),
      },
      systemSettings: {
        findUnique: vi.fn().mockResolvedValue({ vacationDefaultDays: 30 }),
      },
      vacationEntitlement: {
        findUnique: vi.fn().mockResolvedValue(null),
        create: vi.fn().mockResolvedValue({
          id: "ent_2026",
          resourceId: "res_1",
          year: 2026,
          entitledDays: 30,
          carryoverDays: 0,
          usedDays: 0,
          pendingDays: 0,
        }),
        update: vi.fn().mockImplementation(async (args?: any) => ({
          id: "ent_2026",
          resourceId: "res_1",
          year: 2026,
          entitledDays: 30,
          carryoverDays: 0,
          usedDays: args?.data?.usedDays ?? 0,
          pendingDays: args?.data?.pendingDays ?? 0,
        })),
      },
      vacation: {
        findMany: vacationFindMany,
      },
    }, { userRole: SystemRole.ADMIN });

    const result = await executeTool(
      "get_vacation_balance",
      JSON.stringify({ resourceId: "res_1", year: 2026 }),
      ctx,
    );

    expect(JSON.parse(result.content)).toEqual(expect.objectContaining({
      resource: "Alice Example",
      eid: "EMP-001",
      year: 2026,
      entitlement: 30,
      carryOver: 0,
      taken: 1,
      pending: 0.5,
      remaining: 28.5,
      sickDays: 1,
      deductionSummary: {
        formula: "remaining = entitlement - taken - pending",
        approvedVacationCount: 1,
        pendingVacationCount: 1,
        approvedRequestedDays: 2,
        pendingRequestedDays: 0.5,
        approvedDeductedDays: 1,
        pendingDeductedDays: 0.5,
        excludedHolidayDates: ["2026-01-06"],
        holidayBasisVariants: ["Germany / BY"],
        sources: {
          hasCalendarHolidays: true,
          hasLegacyPublicHolidayEntries: false,
        },
      },
      vacations: [
        expect.objectContaining({
          type: "ANNUAL",
          status: "APPROVED",
          startDate: "2026-01-05",
          endDate: "2026-01-06",
          isHalfDay: false,
          requestedDays: 2,
          deductedDays: 1,
          holidayCountryCode: "DE",
          holidayCountryName: "Germany",
          holidayFederalState: "BY",
          holidayMetroCityName: null,
          holidayCalendarDates: ["2026-01-06"],
          holidayLegacyPublicHolidayDates: [],
          holidayDetails: [{ date: "2026-01-06", source: "CALENDAR" }],
          holidayContext: {
            countryCode: "DE",
            countryName: "Germany",
            federalState: "BY",
            metroCityName: null,
            sources: {
              hasCalendarHolidays: true,
              hasLegacyPublicHolidayEntries: false,
            },
          },
        }),
        expect.objectContaining({
          type: "ANNUAL",
          status: "PENDING",
          startDate: "2026-02-03",
          endDate: "2026-02-03",
          isHalfDay: true,
          requestedDays: 0.5,
          deductedDays: 0.5,
          holidayCountryCode: "DE",
          holidayCountryName: "Germany",
          holidayFederalState: "BY",
          holidayMetroCityName: null,
          holidayCalendarDates: [],
          holidayLegacyPublicHolidayDates: [],
          holidayDetails: [],
          holidayContext: {
            countryCode: "DE",
            countryName: "Germany",
            federalState: "BY",
            metroCityName: null,
            sources: {
              hasCalendarHolidays: false,
              hasLegacyPublicHolidayEntries: false,
            },
          },
        }),
      ],
    }));
  });
});
