import { beforeEach, describe, expect, it, vi } from "vitest";
import { DEFAULT_OPENAI_MODEL, 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(),
  };
});

vi.mock("../ai-client.js", async (importOriginal) => {
  const actual = await importOriginal<typeof import("../ai-client.js")>();
  return {
    ...actual,
    createAiClient: vi.fn(() => ({
      chat: {
        completions: {
          create: vi.fn().mockResolvedValue({
            choices: [
              {
                message: {
                  content: "Project is on track overall, but staffing remains partially open.",
                },
              },
            ],
          }),
        },
      },
    })),
    loggedAiCall: vi.fn(async (_provider, _model, _promptLength, fn) => fn()),
  };
});

import {
  createToolContext,
  executeTool,
} from "./assistant-tools-project-media-test-helpers.js";

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

  it("routes project narrative generation through the real insights router path", async () => {
    const projectFindUnique = vi.fn().mockResolvedValue({
      id: "project_1",
      name: "Project One",
      shortCode: "PROJ-1",
      status: "ACTIVE",
      startDate: new Date("2026-03-01T00:00:00.000Z"),
      endDate: new Date("2026-06-30T00:00:00.000Z"),
      budgetCents: 250_000_00,
      dynamicFields: { existingFlag: true },
      demandRequirements: [
        {
          headcount: 2,
          _count: { assignments: 1 },
        },
      ],
      assignments: [
        {
          status: "ACTIVE",
          dailyCostCents: 42_000,
          startDate: new Date("2026-03-10T00:00:00.000Z"),
          endDate: new Date("2026-03-20T00:00:00.000Z"),
          resource: { displayName: "Carol Danvers" },
        },
      ],
    });
    const projectUpdate = vi.fn().mockResolvedValue({
      id: "project_1",
      dynamicFields: {
        existingFlag: true,
        aiNarrative: "Project is on track overall, but staffing remains partially open.",
      },
    });
    const ctx = createToolContext(
      {
        project: {
          findUnique: projectFindUnique,
          update: projectUpdate,
        },
        systemSettings: {
          findUnique: vi.fn().mockResolvedValue({
            id: "singleton",
            aiProvider: "openai",
            azureOpenAiApiKey: "sk-test",
            azureOpenAiDeployment: DEFAULT_OPENAI_MODEL,
          }),
        },
      },
      {
        userRole: SystemRole.CONTROLLER,
      },
    );

    const result = await executeTool(
      "generate_project_narrative",
      JSON.stringify({ projectId: "project_1" }),
      ctx,
    );

    expect(projectFindUnique).toHaveBeenCalledWith({
      where: { id: "project_1" },
      include: {
        demandRequirements: {
          select: {
            id: true,
            role: true,
            headcount: true,
            hoursPerDay: true,
            startDate: true,
            endDate: true,
            status: true,
            _count: { select: { assignments: true } },
          },
        },
        assignments: {
          select: {
            id: true,
            role: true,
            hoursPerDay: true,
            startDate: true,
            endDate: true,
            status: true,
            dailyCostCents: true,
            resource: { select: { displayName: true } },
          },
        },
      },
    });
    expect(projectUpdate).toHaveBeenCalledWith({
      where: { id: "project_1" },
      data: {
        dynamicFields: expect.objectContaining({
          existingFlag: true,
          aiNarrative: "Project is on track overall, but staffing remains partially open.",
          aiNarrativeGeneratedAt: expect.any(String),
        }),
      },
    });
    expect(JSON.parse(result.content)).toEqual(
      expect.objectContaining({
        narrative: "Project is on track overall, but staffing remains partially open.",
        generatedAt: expect.any(String),
      }),
    );
  });
});
