import { beforeEach, describe, expect, it, vi } from "vitest";

vi.mock("../router/timeline-read-shared.js", () => ({
  buildSelfServiceTimelineInput: vi.fn(),
  buildTimelineEntriesDetailInput: vi.fn(),
}));

vi.mock("../router/timeline-holiday-load-support.js", () => ({
  loadTimelineHolidayOverlays: vi.fn(),
}));

vi.mock("../router/timeline-holiday-support.js", () => ({
  buildTimelineHolidayOverlayDetailResponse: vi.fn(),
  formatTimelineHolidayOverlays: vi.fn(),
}));

import {
  buildSelfServiceTimelineInput,
  buildTimelineEntriesDetailInput,
} from "../router/timeline-read-shared.js";
import { loadTimelineHolidayOverlays } from "../router/timeline-holiday-load-support.js";
import {
  buildTimelineHolidayOverlayDetailResponse,
  formatTimelineHolidayOverlays,
} from "../router/timeline-holiday-support.js";
import {
  readMyTimelineHolidayOverlays,
  readTimelineHolidayOverlayDetail,
} from "../router/timeline-holiday-procedure-support.js";

const buildSelfServiceTimelineInputMock = vi.mocked(buildSelfServiceTimelineInput);
const buildTimelineEntriesDetailInputMock = vi.mocked(buildTimelineEntriesDetailInput);
const loadTimelineHolidayOverlaysMock = vi.mocked(loadTimelineHolidayOverlays);
const buildTimelineHolidayOverlayDetailResponseMock = vi.mocked(buildTimelineHolidayOverlayDetailResponse);
const formatTimelineHolidayOverlaysMock = vi.mocked(formatTimelineHolidayOverlays);

describe("timeline holiday procedure support", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("returns an empty list when self-service scope cannot be resolved", async () => {
    buildSelfServiceTimelineInputMock.mockResolvedValueOnce(null);

    await expect(
      readMyTimelineHolidayOverlays(
        { db: {}, dbUser: { id: "user_1" } } as never,
        {
          startDate: new Date("2026-04-01T00:00:00.000Z"),
          endDate: new Date("2026-04-07T00:00:00.000Z"),
        },
      ),
    ).resolves.toEqual([]);

    expect(loadTimelineHolidayOverlaysMock).not.toHaveBeenCalled();
  });

  it("loads self-service holiday overlays when a scope is available", async () => {
    const ctx = { db: {}, dbUser: { id: "user_1" } } as never;
    const input = {
      startDate: new Date("2026-04-01T00:00:00.000Z"),
      endDate: new Date("2026-04-07T00:00:00.000Z"),
    };
    const selfServiceInput = {
      startDate: new Date("2026-04-01T00:00:00.000Z"),
      endDate: new Date("2026-04-07T00:00:00.000Z"),
      resourceIds: ["resource_1"],
    };

    buildSelfServiceTimelineInputMock.mockResolvedValueOnce(selfServiceInput as never);
    loadTimelineHolidayOverlaysMock.mockResolvedValueOnce([{ id: "overlay_1" }] as never);

    await expect(readMyTimelineHolidayOverlays(ctx, input)).resolves.toEqual([{ id: "overlay_1" }]);

    expect(buildSelfServiceTimelineInputMock).toHaveBeenCalledWith(ctx, input);
    expect(loadTimelineHolidayOverlaysMock).toHaveBeenCalledWith(ctx.db, selfServiceInput);
  });

  it("builds holiday overlay detail responses from resolved detail inputs", async () => {
    buildTimelineEntriesDetailInputMock.mockReturnValueOnce({
      period: {
        startDate: new Date("2026-04-01T00:00:00.000Z"),
        endDate: new Date("2026-04-07T00:00:00.000Z"),
      },
      filters: { countryCodes: ["DE"] },
      timelineInput: {
        startDate: new Date("2026-04-01T00:00:00.000Z"),
        endDate: new Date("2026-04-07T00:00:00.000Z"),
        countryCodes: ["DE"],
      },
    } as never);
    loadTimelineHolidayOverlaysMock.mockResolvedValueOnce([{ id: "overlay_1" }] as never);
    formatTimelineHolidayOverlaysMock.mockReturnValueOnce([{ id: "formatted_1" }] as never);
    buildTimelineHolidayOverlayDetailResponseMock.mockReturnValueOnce({ detail: true } as never);

    await expect(
      readTimelineHolidayOverlayDetail({} as never, {
        startDate: "2026-04-01",
        endDate: "2026-04-07",
        countryCodes: ["DE"],
      }),
    ).resolves.toEqual({ detail: true });

    expect(loadTimelineHolidayOverlaysMock).toHaveBeenCalledWith({}, {
      startDate: new Date("2026-04-01T00:00:00.000Z"),
      endDate: new Date("2026-04-07T00:00:00.000Z"),
      countryCodes: ["DE"],
    });
    expect(formatTimelineHolidayOverlaysMock).toHaveBeenCalledWith([{ id: "overlay_1" }]);
    expect(buildTimelineHolidayOverlayDetailResponseMock).toHaveBeenCalledWith({
      startDate: new Date("2026-04-01T00:00:00.000Z"),
      endDate: new Date("2026-04-07T00:00:00.000Z"),
      filters: { countryCodes: ["DE"] },
      overlays: [{ id: "formatted_1" }],
    });
  });
});
