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

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

vi.mock("../sse/event-bus.js", () => ({
  emitAllocationCreated: vi.fn(),
  emitAllocationDeleted: vi.fn(),
  emitAllocationUpdated: vi.fn(),
  emitProjectShifted: vi.fn(),
}));

vi.mock("../lib/budget-alerts.js", () => ({
  checkBudgetThresholds: vi.fn(),
}));

vi.mock("../lib/cache.js", () => ({
  invalidateDashboardCache: vi.fn(),
}));

import { executeTool } from "../router/assistant-tools.js";
import { createToolContext } from "./assistant-tools-advanced-timeline-test-helpers.js";
import { createResourceRankingTestDb } from "./assistant-tools-advanced-resource-ranking-test-helpers.js";

describe("assistant advanced timeline resource ranking tools", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("finds the best project resource with holiday-aware remaining capacity and LCR ranking", async () => {
    const { db } = createResourceRankingTestDb();
    const ctx = createToolContext(
      db,
      [
        PermissionKey.VIEW_PLANNING,
        PermissionKey.VIEW_COSTS,
        PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS,
      ],
    );

    const result = await executeTool(
      "find_best_project_resource",
      JSON.stringify({
        projectIdentifier: "LARI",
        startDate: "2026-01-05",
        endDate: "2026-01-16",
        minHoursPerDay: 3,
        rankingMode: "lowest_lcr",
      }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      project: { shortCode: string };
      candidateCount: number;
      bestMatch: {
        name: string;
        remainingHoursPerDay: number;
        lcrCents: number | null;
        federalState: string | null;
        metroCity: string | null;
        baseAvailableHours: number;
        holidaySummary: { count: number };
      };
      candidates: Array<{
        name: string;
        remainingHoursPerDay: number;
        workingDays: number;
        baseAvailableHours: number;
        holidaySummary: { count: number; hoursDeduction: number };
        capacityBreakdown: { holidayHoursDeduction: number };
      }>;
    };

    expect(parsed.project.shortCode).toBe("LARI");
    expect(parsed.candidateCount).toBe(2);
    expect(parsed.bestMatch).toEqual(
      expect.objectContaining({
        name: "Carol Danvers",
        remainingHoursPerDay: 6,
        lcrCents: 7664,
        federalState: "HH",
        metroCity: "Hamburg",
        baseAvailableHours: 80,
        holidaySummary: expect.objectContaining({ count: 0 }),
      }),
    );
    expect(parsed.candidates).toEqual([
      expect.objectContaining({
        name: "Carol Danvers",
        remainingHoursPerDay: 6,
        workingDays: 10,
        baseAvailableHours: 80,
        holidaySummary: expect.objectContaining({ count: 0, hoursDeduction: 0 }),
        capacityBreakdown: expect.objectContaining({ holidayHoursDeduction: 0 }),
      }),
      expect.objectContaining({
        name: "Steve Rogers",
        remainingHoursPerDay: 4,
        workingDays: 9,
        baseAvailableHours: 80,
        holidaySummary: expect.objectContaining({ count: 1, hoursDeduction: 8 }),
        capacityBreakdown: expect.objectContaining({ holidayHoursDeduction: 8 }),
      }),
    ]);
  });

  it("requires the dedicated advanced assistant permission for the high-level resource tool", async () => {
    const ctx = createToolContext({}, [
      PermissionKey.VIEW_PLANNING,
      PermissionKey.VIEW_COSTS,
    ]);

    const result = await executeTool(
      "find_best_project_resource",
      JSON.stringify({ projectIdentifier: "LARI" }),
      ctx,
    );

    expect(JSON.parse(result.content)).toEqual(
      expect.objectContaining({
        error: expect.stringContaining(PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS),
      }),
    );
  });
});
