import { describe, expect, test } from "bun:test";
import {
	formatRecurrenceText,
	getRecurrencePreview,
	parseRecurrenceRule,
	serializeRecurrenceRule,
	validateRecurrence,
} from "@/lib/recurrence";

describe("recurrence helpers", () => {
	test("serializes a weekly weekday recurrence into an RFC5545 RRULE string", () => {
		const rule = serializeRecurrenceRule({
			freq: "WEEKLY",
			interval: 2,
			byDay: ["TU", "TH"],
			until: "2026-06-30",
		});

		expect(rule).toBe("FREQ=WEEKLY;INTERVAL=2;UNTIL=20260630T235959Z;BYDAY=TU,TH");
	});

	test("rehydrates an existing RRULE string into picker-friendly values", () => {
		const parsed = parseRecurrenceRule(
			"FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE,FR;COUNT=6",
		);

		expect(parsed).toEqual({
			freq: "WEEKLY",
			interval: 1,
			byDay: ["MO", "WE", "FR"],
			count: 6,
			until: undefined,
		});
	});

	test("returns a preview of upcoming recurrence instances from the public helper", () => {
		const preview = getRecurrencePreview(
			{
				freq: "MONTHLY",
				interval: 1,
				byDay: [],
				count: 3,
			},
			"2026-04-09T10:00:00.000Z",
		);

		expect(preview).toHaveLength(3);
		expect(preview[0]).toContain("2026-04-09T10:00:00.000Z");
		expect(preview[1]).toContain("2026-05-09T10:00:00.000Z");
		expect(preview[2]).toContain("2026-06-09T10:00:00.000Z");
	});

	test("rejects invalid recurrence endings that mix count and until", () => {
		const result = validateRecurrence({
			freq: "DAILY",
			interval: 1,
			byDay: [],
			count: 5,
			until: "2026-05-01",
		});

		expect(result.isValid).toBe(false);
		expect(result.errors.rule).toContain("either count or until");
	});

	test("rejects malformed count inputs", () => {
		const result = validateRecurrence({
			freq: "MONTHLY",
			interval: 1,
			byDay: [],
			count: 0,
		});

		expect(result.isValid).toBe(false);
		expect(result.errors.count).toContain("greater than 0");
	});

	test("formats supported recurrence strings into human text", () => {
		expect(formatRecurrenceText("FREQ=WEEKLY;INTERVAL=1;BYDAY=MO,WE")).toContain(
			"every week",
		);
	});
});
