import { describe, it, expect } from "vitest";
import { computeAlertWindow } from "../services/invoice-alerts";
import { utcMidnightOfLocalDay } from "../utils/date";

// Pure tests — no DB rows are touched. due_date is @db.Date: Prisma truncates
// a Date used in a WHERE filter to its UTC date part, so the alert window
// boundaries must be UTC midnights of the LOCAL calendar day. The old code
// used local midnights (= 22:00/23:00 UTC of the PREVIOUS day), which shifted
// the [today, today+3] due_date window a day early — the "splatnost za 3 dny"
// advance alert (due == today+3) could then never fire. All assertions below
// are timezone-independent (inputs are built from local components).

describe("utcMidnightOfLocalDay", () => {
  it("preserves the LOCAL calendar day shortly after local midnight (the night window)", () => {
    // 00:30 local on 2098-07-01 — in Prague (UTC+2) this instant is
    // 2098-06-30T22:30Z, i.e. its UTC date part is the PREVIOUS day, which is
    // exactly what Prisma would truncate a bare Date to.
    const justAfterMidnight = new Date(2098, 6, 1, 0, 30, 0);
    expect(utcMidnightOfLocalDay(justAfterMidnight).getTime()).toBe(
      Date.UTC(2098, 6, 1),
    );
  });

  it("returns UTC midnight of the local day for a mid-day instant", () => {
    const noon = new Date(2098, 0, 15, 12, 0, 0);
    expect(utcMidnightOfLocalDay(noon).getTime()).toBe(Date.UTC(2098, 0, 15));
  });
});

describe("computeAlertWindow", () => {
  it("builds [today, today+3] as UTC midnights of the LOCAL day, with matching strings", () => {
    // 00:30 local — the window where the old local-midnight computation
    // produced yesterday's UTC date and the whole window slid a day early.
    const now = new Date(2098, 6, 1, 0, 30, 0);
    const w = computeAlertWindow(now);

    expect(w.today.getTime()).toBe(Date.UTC(2098, 6, 1));
    expect(w.in3days.getTime()).toBe(Date.UTC(2098, 6, 4));
    expect(w.todayStr).toBe("2098-07-01");
    expect(w.in3daysStr).toBe("2098-07-04");
  });

  it("rolls the +3-day bound over a month boundary", () => {
    const now = new Date(2098, 0, 30, 8, 0, 0); // 2098-01-30
    const w = computeAlertWindow(now);

    expect(w.in3days.getTime()).toBe(Date.UTC(2098, 1, 2)); // 2098-02-02
    expect(w.in3daysStr).toBe("2098-02-02");
  });
});
