import { describe, test, expect } from "bun:test";
import {
  getCalendarDateInTimeZone,
  getHourInTimeZone,
  getDayOfWeekInTimeZone,
} from "@/utils/timezone.js";

// Fixed instant: 2026-01-15T02:00:00Z
// UTC:                     Thu Jan 15, 02:00
// Buenos Aires (UTC-3):    Wed Jan 14, 23:00
// Tokyo (UTC+9):           Thu Jan 15, 11:00
const JAN_15_0200Z = new Date("2026-01-15T02:00:00Z");

// Fixed instant: 2026-01-15T20:00:00Z
// UTC:                     Thu Jan 15, 20:00
// Tokyo (UTC+9):           Fri Jan 16, 05:00
const JAN_15_2000Z = new Date("2026-01-15T20:00:00Z");

describe("getCalendarDateInTimeZone", () => {
  test("returns previous day in Buenos Aires when UTC is early morning", () => {
    expect(getCalendarDateInTimeZone(JAN_15_0200Z, "America/Argentina/Buenos_Aires")).toBe(
      "2026-01-14",
    );
  });

  test("returns same day in UTC", () => {
    expect(getCalendarDateInTimeZone(JAN_15_0200Z, "UTC")).toBe("2026-01-15");
  });

  test("returns next day in Tokyo when UTC is late evening", () => {
    expect(getCalendarDateInTimeZone(JAN_15_2000Z, "Asia/Tokyo")).toBe("2026-01-16");
  });
});

describe("getHourInTimeZone", () => {
  test("returns hour 2 in UTC for 02:00Z", () => {
    expect(getHourInTimeZone(JAN_15_0200Z, "UTC")).toBe(2);
  });

  test("returns hour 23 in Buenos Aires for 02:00Z (UTC-3)", () => {
    expect(getHourInTimeZone(JAN_15_0200Z, "America/Argentina/Buenos_Aires")).toBe(23);
  });

  test("returns hour 5 in Tokyo for 20:00Z (UTC+9)", () => {
    expect(getHourInTimeZone(JAN_15_2000Z, "Asia/Tokyo")).toBe(5);
  });
});

describe("getDayOfWeekInTimeZone", () => {
  test("returns 4 (Thu) for Thursday in UTC", () => {
    expect(getDayOfWeekInTimeZone(JAN_15_0200Z, "UTC")).toBe(4);
  });

  test("returns 3 (Wed) in Buenos Aires when date crosses day boundary backward", () => {
    expect(getDayOfWeekInTimeZone(JAN_15_0200Z, "America/Argentina/Buenos_Aires")).toBe(3);
  });

  test("returns 5 (Fri) in Tokyo when date crosses day boundary forward", () => {
    expect(getDayOfWeekInTimeZone(JAN_15_2000Z, "Asia/Tokyo")).toBe(5);
  });
});

describe("invalid timezone", () => {
  test("throws RangeError for an unrecognized IANA timezone", () => {
    expect(() => getCalendarDateInTimeZone(JAN_15_0200Z, "Not/Real")).toThrow(RangeError);
  });
});
