import { beforeEach, describe, expect, it, vi } from "vitest";
import { listAssignmentBookings } from "@capakraken/application";
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-insights-scenarios-test-helpers.js";

describe("assistant scenario tools", () => {
  beforeEach(() => {
    vi.clearAllMocks();
    vi.mocked(listAssignmentBookings).mockResolvedValue([]);
  });

  it("routes scenario simulation through the scenario router path", async () => {
    const db = {
      project: {
        findUnique: vi.fn().mockResolvedValue({
          id: "project_1",
          name: "Gelddruckmaschine",
          budgetCents: 200_000,
          orderType: "CHARGEABLE",
          startDate: new Date("2026-04-01T00:00:00.000Z"),
          endDate: new Date("2026-04-30T00:00:00.000Z"),
        }),
      },
      assignment: {
        findMany: vi
          .fn()
          .mockResolvedValueOnce([
            {
              id: "assign_1",
              resourceId: "res_1",
              projectId: "project_1",
              hoursPerDay: 4,
              startDate: new Date("2026-04-01T00:00:00.000Z"),
              endDate: new Date("2026-04-03T00:00:00.000Z"),
              status: "ACTIVE",
              roleId: null,
              role: "Pipeline TD",
              resource: {
                id: "res_1",
                displayName: "Bruce Banner",
                eid: "EMP-001",
                lcrCents: 10_000,
                availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
                chargeabilityTarget: 80,
                skills: [{ skill: "Houdini" }],
                countryId: null,
                federalState: null,
                metroCityId: null,
                country: null,
                metroCity: null,
              },
              roleEntity: null,
            },
          ])
          .mockResolvedValueOnce([
            {
              id: "assign_1",
              resourceId: "res_1",
              projectId: "project_1",
              hoursPerDay: 4,
              startDate: new Date("2026-04-01T00:00:00.000Z"),
              endDate: new Date("2026-04-03T00:00:00.000Z"),
            },
          ]),
      },
      resource: {
        findMany: vi.fn().mockResolvedValue([
          {
            id: "res_1",
            displayName: "Bruce Banner",
            eid: "EMP-001",
            lcrCents: 10_000,
            availability: { monday: 8, tuesday: 8, wednesday: 8, thursday: 8, friday: 8 },
            chargeabilityTarget: 80,
            skills: [{ skill: "Houdini" }],
            countryId: null,
            federalState: null,
            metroCityId: null,
            country: null,
            metroCity: null,
          },
        ]),
      },
      role: {
        findMany: vi.fn(),
      },
    };
    const ctx = createToolContext(db, { userRole: SystemRole.CONTROLLER });

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

    expect(db.assignment.findMany).toHaveBeenNthCalledWith(1, {
      where: { projectId: "project_1", status: { not: "CANCELLED" } },
      include: {
        resource: {
          select: {
            id: true,
            displayName: true,
            eid: true,
            lcrCents: true,
            availability: true,
            chargeabilityTarget: true,
            skills: true,
            countryId: true,
            federalState: true,
            metroCityId: true,
            country: { select: { code: true } },
            metroCity: { select: { name: true } },
          },
        },
      },
    });
    expect(db.assignment.findMany).toHaveBeenNthCalledWith(2, {
      where: {
        resourceId: { in: ["res_1"] },
        status: { not: "CANCELLED" },
      },
      select: {
        id: true,
        resourceId: true,
        projectId: true,
        hoursPerDay: true,
        startDate: true,
        endDate: true,
      },
    });
    expect(db.role.findMany).not.toHaveBeenCalled();
    expect(JSON.parse(result.content)).toEqual({
      baseline: {
        totalCostCents: 120000,
        totalHours: 12,
        headcount: 1,
        skillCount: 1,
        totalCost: "1.200,00 EUR",
      },
      scenario: {
        totalCostCents: 180000,
        totalHours: 18,
        headcount: 1,
        skillCount: 1,
        totalCost: "1.800,00 EUR",
      },
      delta: {
        costCents: 60000,
        hours: 6,
        headcount: 0,
        skillCoveragePct: 100,
        cost: "600,00 EUR",
      },
      resourceImpacts: [
        {
          resourceId: "res_1",
          resourceName: "Bruce Banner",
          chargeabilityTarget: 80,
          currentUtilization: 6.8,
          scenarioUtilization: 10.2,
          utilizationDelta: 3.4,
          isOverallocated: false,
        },
      ],
      warnings: [],
      budgetCents: 200000,
    });
  });
});
