import { describe, expect, it, vi, beforeEach, afterEach } from "vitest";
import {
  BOARD_WINDOW_DAYS_BACK,
  BOARD_WINDOW_DAYS_FORWARD,
  SCHEDULE_WINDOW_DAYS_BACK,
  SCHEDULE_WINDOW_DAYS_FORWARD,
  MAP_WINDOW_DAYS_BACK,
  MAP_WINDOW_MONTHS_FORWARD,
  isInBoardWindow,
  isInScheduleWindow,
  isInMapWindow,
  boardWindowBounds,
  scheduleWindowBounds,
  mapWindowBounds,
} from "./dateWindow.js";

describe("dateWindow constants", () => {
  it("exports the TZ-defined numerical bounds", () => {
    expect(BOARD_WINDOW_DAYS_BACK).toBe(1);
    expect(BOARD_WINDOW_DAYS_FORWARD).toBe(14);
    expect(SCHEDULE_WINDOW_DAYS_BACK).toBe(1);
    expect(SCHEDULE_WINDOW_DAYS_FORWARD).toBe(330);
    expect(MAP_WINDOW_DAYS_BACK).toBe(1);
    expect(MAP_WINDOW_MONTHS_FORWARD).toBe(6);
  });
});

describe("dateWindow helpers (clock frozen at 2026-05-15)", () => {
  beforeEach(() => {
    vi.useFakeTimers();
    vi.setSystemTime(new Date(2026, 4, 15, 12, 0, 0)); // May 15, 2026 noon local time
  });
  afterEach(() => {
    vi.useRealTimers();
  });

  // Helper to format date as YYYY-MM-DD for comparison
  function toYmd(d: Date): string {
    return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
  }

  describe("4.1.2-R12: isInBoardWindow (-1/+14 days)", () => {
    it("accepts today (yyyyMMdd)", () => {
      expect(isInBoardWindow("20260515")).toBe(true);
    });
    it("accepts yesterday (-1 day)", () => {
      expect(isInBoardWindow("20260514")).toBe(true);
    });
    it("rejects -2 days", () => {
      expect(isInBoardWindow("20260513")).toBe(false);
    });
    it("accepts today + 14 days", () => {
      expect(isInBoardWindow("20260529")).toBe(true);
    });
    it("rejects today + 15 days", () => {
      expect(isInBoardWindow("20260530")).toBe(false);
    });
    it("rejects malformed input", () => {
      expect(isInBoardWindow("")).toBe(false);
      expect(isInBoardWindow("2026-05-15")).toBe(false);
      expect(isInBoardWindow("20269999")).toBe(false);
    });
  });

  describe("4.1.2-R12: isInScheduleWindow (-1/+330 days)", () => {
    it("accepts today + 330 days", () => {
      expect(isInScheduleWindow("20270410")).toBe(true);
    });
    it("rejects today + 331 days", () => {
      expect(isInScheduleWindow("20270411")).toBe(false);
    });
    it("rejects -2 days", () => {
      expect(isInScheduleWindow("20260513")).toBe(false);
    });
  });

  describe("4.1.2-R12: isInMapWindow (-1 day / +6 months)", () => {
    it("accepts today + 6 months (same calendar day)", () => {
      expect(isInMapWindow("20261115")).toBe(true);
    });
    it("rejects today + 6 months + 1 day", () => {
      expect(isInMapWindow("20261116")).toBe(false);
    });
    it("rejects -2 days", () => {
      expect(isInMapWindow("20260513")).toBe(false);
    });
  });

  it("exposes bounds tuples for UI consumers", () => {
    const [bMin, bMax] = boardWindowBounds();
    expect(toYmd(bMin)).toBe("2026-05-14");
    expect(toYmd(bMax)).toBe("2026-05-29");
    const [sMin, sMax] = scheduleWindowBounds();
    expect(toYmd(sMin)).toBe("2026-05-14");
    expect(toYmd(sMax)).toBe("2027-04-10");
    const [mMin, mMax] = mapWindowBounds();
    expect(toYmd(mMin)).toBe("2026-05-14");
    expect(toYmd(mMax)).toBe("2026-11-15");
  });
});
