import { beforeEach, describe, expect, it, vi } from "vitest";
import { TRPCError } from "@trpc/server";

import {
  buildBaseProject,
  buildBaseResource,
  createQuickAssignInput,
  createToolContext,
  executeTool,
  quickAssignPermissions,
  quickAssignRole,
} from "./assistant-tools-timeline-quick-assign-test-helpers.js";

describe("assistant timeline quick-assign error tools", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns a stable conflict error for quick-assign timeline mutations", async () => {
    const db = {
      project: {
        findUnique: vi.fn().mockResolvedValue(buildBaseProject()),
      },
      resource: {
        findUnique: vi.fn().mockResolvedValue(buildBaseResource()),
      },
      assignment: {
        findMany: vi.fn().mockResolvedValue([]),
        create: vi.fn().mockRejectedValue(
          new TRPCError({
            code: "CONFLICT",
            message: "Resource is already assigned to this project with overlapping dates",
          }),
        ),
      },
      vacation: {
        findMany: vi.fn().mockResolvedValue([]),
      },
      auditLog: {
        create: vi.fn().mockResolvedValue({}),
      },
      $transaction: vi.fn(async (callback: (tx: unknown) => unknown) => callback(db)),
    };
    const ctx = createToolContext(db, quickAssignPermissions, quickAssignRole);

    const result = await executeTool(
      "quick_assign_timeline_resource",
      JSON.stringify(createQuickAssignInput()),
      ctx,
    );

    expect(result.action).toBeUndefined();
    expect(JSON.parse(result.content)).toEqual({
      error: "Resource is already assigned to this project with overlapping dates",
    });
  });

  it("returns stable not-found errors when quick-assign timeline targets disappear mid-mutation", async () => {
    const cases = [
      {
        name: "missing project",
        tx: {
          project: {
            findUnique: vi.fn().mockResolvedValue(null),
          },
          resource: {
            findUnique: vi.fn().mockResolvedValue(buildBaseResource()),
          },
          assignment: {
            findMany: vi.fn().mockResolvedValue([]),
            create: vi.fn(),
          },
        },
        expected: "Project not found with the given criteria.",
      },
      {
        name: "missing resource",
        tx: {
          project: {
            findUnique: vi.fn().mockResolvedValue(buildBaseProject()),
          },
          resource: {
            findUnique: vi.fn().mockResolvedValue(null),
          },
          assignment: {
            findMany: vi.fn().mockResolvedValue([]),
            create: vi.fn(),
          },
        },
        expected: "Resource not found with the given criteria.",
      },
    ] as const;

    for (const testCase of cases) {
      const db = {
        project: {
          findUnique: vi.fn().mockResolvedValue(buildBaseProject()),
        },
        resource: {
          findUnique: vi.fn().mockResolvedValue(buildBaseResource()),
        },
        assignment: {
          findMany: vi.fn().mockResolvedValue([]),
          create: vi.fn(),
        },
        vacation: {
          findMany: vi.fn().mockResolvedValue([]),
        },
        auditLog: {
          create: vi.fn().mockResolvedValue({}),
        },
        $transaction: vi.fn(async (callback: (tx: typeof testCase.tx) => unknown) => callback(testCase.tx)),
      };
      const ctx = createToolContext(db, quickAssignPermissions, quickAssignRole);

      const result = await executeTool(
        "quick_assign_timeline_resource",
        JSON.stringify(createQuickAssignInput()),
        ctx,
      );

      expect(JSON.parse(result.content)).toEqual({ error: testCase.expected });
    }
  });

  it("returns a stable validation error for quick-assign timeline date ranges", async () => {
    const ctx = createToolContext(
      {
        project: {
          findUnique: vi.fn().mockResolvedValue(buildBaseProject()),
        },
        resource: {
          findUnique: vi.fn().mockResolvedValue(buildBaseResource()),
        },
      },
      quickAssignPermissions,
      quickAssignRole,
    );

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

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