/**
 * Unit tests for calendar-data: dutiesByDate (including edge case end_at < start_at),
 * calendarEventsByDate. Ported from webapp/js/calendar.test.js.
 */

import { describe, it, expect } from "vitest";
import { dutiesByDate, calendarEventsByDate } from "./calendar-data";
import type { DutyWithUser } from "@/types";
import type { CalendarEvent } from "@/types";

describe("dutiesByDate", () => {
  it("groups duty by single local day", () => {
    const duties: DutyWithUser[] = [
      {
        id: 1,
        user_id: 1,
        full_name: "Alice",
        start_at: "2025-02-25T09:00:00Z",
        end_at: "2025-02-25T18:00:00Z",
        event_type: "duty",
        phone: null,
        username: null,
      },
    ];
    const byDate = dutiesByDate(duties);
    expect(byDate["2025-02-25"]).toHaveLength(1);
    expect(byDate["2025-02-25"][0].full_name).toBe("Alice");
  });

  it("spans duty across multiple days", () => {
    const duties: DutyWithUser[] = [
      {
        id: 1,
        user_id: 1,
        full_name: "Bob",
        start_at: "2025-02-25T00:00:00Z",
        end_at: "2025-02-27T23:59:59Z",
        event_type: "duty",
        phone: null,
        username: null,
      },
    ];
    const byDate = dutiesByDate(duties);
    const keys = Object.keys(byDate).sort();
    expect(keys.length).toBeGreaterThanOrEqual(2);
    keys.forEach((k) => expect(byDate[k]).toHaveLength(1));
    expect(byDate[keys[0]][0].full_name).toBe("Bob");
  });

  it("skips duty when end_at < start_at (no infinite loop)", () => {
    const duties: DutyWithUser[] = [
      {
        id: 1,
        user_id: 1,
        full_name: "Bad",
        start_at: "2025-02-28T12:00:00Z",
        end_at: "2025-02-25T08:00:00Z",
        event_type: "duty",
        phone: null,
        username: null,
      },
    ];
    const byDate = dutiesByDate(duties);
    expect(Object.keys(byDate)).toHaveLength(0);
  });

  it("does not iterate more than MAX_DAYS_PER_DUTY", () => {
    const duties: DutyWithUser[] = [
      {
        id: 1,
        user_id: 1,
        full_name: "Long",
        start_at: "2025-01-01T00:00:00Z",
        end_at: "2026-06-01T00:00:00Z",
        event_type: "duty",
        phone: null,
        username: null,
      },
    ];
    const byDate = dutiesByDate(duties);
    const keys = Object.keys(byDate).sort();
    expect(keys.length).toBeLessThanOrEqual(367);
  });

  it("handles empty duties", () => {
    expect(dutiesByDate([])).toEqual({});
  });
});

describe("calendarEventsByDate", () => {
  it("maps events to local date key by UTC date", () => {
    const events: CalendarEvent[] = [
      { date: "2025-02-25", summary: "Holiday" },
      { date: "2025-02-25", summary: "Meeting" },
      { date: "2025-02-26", summary: "Other" },
    ];
    const byDate = calendarEventsByDate(events);
    expect(byDate["2025-02-25"]).toEqual(["Holiday", "Meeting"]);
    expect(byDate["2025-02-26"]).toEqual(["Other"]);
  });

  it("skips events without summary", () => {
    const events = [
      { date: "2025-02-25", summary: null as unknown as string },
    ];
    const byDate = calendarEventsByDate(events);
    expect(byDate["2025-02-25"] ?? []).toHaveLength(0);
  });

  it("handles null or undefined events", () => {
    expect(calendarEventsByDate(null)).toEqual({});
    expect(calendarEventsByDate(undefined)).toEqual({});
  });
});
