import { beforeEach, describe, expect, it, vi } from "vitest";
import { PermissionKey, SystemRole } 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 {
  baseAvailability,
  buildBaseAssignment,
} from "./assistant-tools-timeline-allocation-mutation-test-helpers.js";

describe("assistant timeline inline allocation update error tools", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns a stable validation error for inline timeline mutation date ranges", async () => {
    const ctx = createToolContext(
      {
        allocation: {
          findUnique: vi.fn().mockResolvedValue(null),
        },
        demandRequirement: {
          findUnique: vi.fn().mockResolvedValue(null),
        },
        assignment: {
          findUnique: vi.fn().mockResolvedValue(buildBaseAssignment()),
        },
        resource: {
          findUnique: vi.fn().mockResolvedValue({
            id: "resource_1",
            lcrCents: 5000,
            availability: baseAvailability,
          }),
        },
      },
      [PermissionKey.MANAGE_ALLOCATIONS, PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS],
      SystemRole.MANAGER,
    );

    const result = await executeTool(
      "update_timeline_allocation_inline",
      JSON.stringify({
        allocationId: "assignment_1",
        startDate: "2026-03-20",
        endDate: "2026-03-16",
      }),
      ctx,
    );

    expect(JSON.parse(result.content)).toEqual({
      error: "End date must be after start date",
    });
  });

  it("returns a stable allocation-not-found error for inline timeline updates", async () => {
    const db = {
      allocation: {
        findUnique: vi.fn().mockResolvedValue(null),
      },
      demandRequirement: {
        findUnique: vi.fn().mockResolvedValue(null),
      },
      assignment: {
        findUnique: vi.fn().mockResolvedValue(null),
      },
    };
    const ctx = createToolContext(
      db,
      [PermissionKey.MANAGE_ALLOCATIONS, PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS],
      SystemRole.MANAGER,
    );

    const result = await executeTool(
      "update_timeline_allocation_inline",
      JSON.stringify({
        allocationId: "assignment_missing",
        hoursPerDay: 6,
      }),
      ctx,
    );

    expect(result.action).toBeUndefined();
    expect(JSON.parse(result.content)).toEqual({
      error: "Allocation not found with the given criteria.",
    });
  });

  it("returns stable allocation-not-found errors when timeline allocation persistence loses the row", async () => {
    const missingDuringUpdate = {
      code: "P2025",
      message: "Record to update not found",
      meta: { modelName: "Assignment" },
    };

    const updateInlineCtx = createToolContext(
      {
        allocation: {
          findUnique: vi.fn().mockResolvedValue(null),
        },
        demandRequirement: {
          findUnique: vi.fn().mockResolvedValue(null),
        },
        assignment: {
          findUnique: vi.fn().mockResolvedValue(buildBaseAssignment()),
        },
        resource: {
          findUnique: vi.fn().mockResolvedValue({
            id: "resource_1",
            lcrCents: 5000,
            availability: baseAvailability,
          }),
        },
        auditLog: {
          create: vi.fn().mockResolvedValue({}),
        },
        vacation: {
          findMany: vi.fn().mockResolvedValue([]),
        },
        $transaction: vi.fn(async () => {
          throw missingDuringUpdate;
        }),
      },
      [PermissionKey.MANAGE_ALLOCATIONS, PermissionKey.USE_ASSISTANT_ADVANCED_TOOLS],
      SystemRole.MANAGER,
    );

    const updateInlineResult = await executeTool(
      "update_timeline_allocation_inline",
      JSON.stringify({
        allocationId: "assignment_1",
        hoursPerDay: 6,
      }),
      updateInlineCtx,
    );

    expect(JSON.parse(updateInlineResult.content)).toEqual({
      error: "Allocation not found with the given criteria.",
    });
  });
});
