import { beforeEach, describe, expect, it, vi } from "vitest";
import { PermissionKey } from "@capakraken/shared";

import { executeTool } from "../router/assistant-tools.js";
import { createToolContext } from "./assistant-tools-country-test-helpers.js";

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

  it("gets a country by identifier and falls back from id to code and name lookup", async () => {
    const db = {
      country: {
        findUnique: vi.fn().mockResolvedValue(null),
        findFirst: vi
          .fn()
          .mockResolvedValueOnce({
            id: "country_es",
            code: "ES",
            name: "Spain",
            dailyWorkingHours: 8,
            scheduleRules: {
              type: "spain",
              fridayHours: 6.5,
              summerPeriod: { from: "07-01", to: "09-15" },
              summerHours: 6.5,
              regularHours: 9,
            },
            isActive: true,
            metroCities: [{ id: "city_mad", name: "Madrid" }],
            _count: { resources: 4 },
          })
          .mockResolvedValueOnce(null)
          .mockResolvedValueOnce({
            id: "country_de",
            code: "DE",
            name: "Germany",
            dailyWorkingHours: 8,
            scheduleRules: null,
            isActive: true,
            metroCities: [{ id: "city_muc", name: "Munich" }],
            _count: { resources: 12 },
          }),
      },
    };
    const ctx = createToolContext(db, [PermissionKey.VIEW_ALL_RESOURCES]);

    const result = await executeTool(
      "get_country",
      JSON.stringify({ identifier: "ES" }),
      ctx,
    );

    const parsed = JSON.parse(result.content) as {
      code: string;
      resourceCount: number | null;
      scheduleRules: { type: string };
      metroCities: Array<{ name: string }>;
    };

    expect(parsed).toMatchObject({
      code: "ES",
      resourceCount: 4,
      scheduleRules: { type: "spain" },
      metroCities: [{ name: "Madrid" }],
    });

    const fallbackResult = await executeTool(
      "get_country",
      JSON.stringify({ identifier: "Germany" }),
      ctx,
    );

    expect(db.country.findUnique).toHaveBeenNthCalledWith(1, {
      where: { id: "ES" },
      include: {
        metroCities: { orderBy: { name: "asc" } },
        _count: { select: { resources: true } },
      },
    });
    expect(db.country.findUnique).toHaveBeenNthCalledWith(2, {
      where: { id: "Germany" },
      include: {
        metroCities: { orderBy: { name: "asc" } },
        _count: { select: { resources: true } },
      },
    });
    expect(db.country.findFirst).toHaveBeenNthCalledWith(1, {
      where: { code: { equals: "ES", mode: "insensitive" } },
      include: {
        metroCities: { orderBy: { name: "asc" } },
        _count: { select: { resources: true } },
      },
    });
    expect(db.country.findFirst).toHaveBeenNthCalledWith(2, {
      where: { code: { equals: "GERMANY", mode: "insensitive" } },
      include: {
        metroCities: { orderBy: { name: "asc" } },
        _count: { select: { resources: true } },
      },
    });
    expect(db.country.findFirst).toHaveBeenNthCalledWith(3, {
      where: { name: { equals: "Germany", mode: "insensitive" } },
      include: {
        metroCities: { orderBy: { name: "asc" } },
        _count: { select: { resources: true } },
      },
    });
    expect(JSON.parse(fallbackResult.content)).toEqual({
      id: "country_de",
      code: "DE",
      name: "Germany",
      dailyWorkingHours: 8,
      scheduleRules: null,
      isActive: true,
      resourceCount: 12,
      metroCities: [{ id: "city_muc", name: "Munich" }],
      cities: ["Munich"],
    });
  });

  it("returns a stable error when a country cannot be resolved", async () => {
    const ctx = createToolContext({
      country: {
        findUnique: vi.fn().mockResolvedValue(null),
        findFirst: vi.fn().mockResolvedValue(null),
      },
    }, [PermissionKey.VIEW_ALL_RESOURCES]);

    const result = await executeTool(
      "get_country",
      JSON.stringify({ identifier: "Atlantis" }),
      ctx,
    );

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