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

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

  it("updates timeline allocations inline through the real timeline router mutation", async () => {
    const existingAssignment = {
      ...buildBaseAssignment(),
      status: AllocationStatus.PROPOSED,
    };
    const updatedAssignment = {
      ...existingAssignment,
      hoursPerDay: 6,
      endDate: new Date("2026-03-21"),
      percentage: 75,
      dailyCostCents: 30000,
      metadata: { includeSaturday: true },
      updatedAt: new Date("2026-03-14"),
    };

    const db = {
      allocation: {
        findUnique: vi.fn().mockResolvedValue(null),
      },
      demandRequirement: {
        findUnique: vi.fn().mockResolvedValue(null),
      },
      assignment: {
        findUnique: vi.fn().mockResolvedValue(existingAssignment),
        update: vi.fn().mockResolvedValue(updatedAssignment),
      },
      resource: {
        findUnique: vi.fn().mockResolvedValue(buildBaseResource()),
      },
      vacation: {
        findMany: vi.fn().mockResolvedValue([]),
      },
      auditLog: {
        create: vi.fn().mockResolvedValue({}),
      },
      $transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
    };
    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_1",
        hoursPerDay: 6,
        endDate: "2026-03-21",
        includeSaturday: true,
      }),
      ctx,
    );

    expect(result.action).toEqual({ type: "invalidate", scope: ["allocation", "timeline", "project"] });
    expect(JSON.parse(result.content)).toEqual(
      expect.objectContaining({
        success: true,
        allocation: expect.objectContaining({
          id: "assignment_1",
          hoursPerDay: 6,
          endDate: "2026-03-21",
        }),
      }),
    );
    expect(db.assignment.update).toHaveBeenCalledWith(
      expect.objectContaining({
        where: { id: "assignment_1" },
      }),
    );
  });
});
