/**
 * Schedule Launch Banner — unit tests.
 *
 * Purpose: verify the banner prints due entries to stderr and stays quiet
 * when nothing is due.
 *
 * Consumer: CI test runner (vitest).
 */
import assert from "node:assert/strict";
import { mkdirSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, beforeEach, describe, it } from "vitest";
import { createScheduleStore } from "../schedule/schedule-store.js";
import { generateULID } from "../schedule/schedule-ulid.js";
import {
	printScheduleBanner,
	showScheduleBanner,
} from "../schedule-launch-banner.js";

function captureStderr(fn) {
	const chunks = [];
	const original = process.stderr.write.bind(process.stderr);
	process.stderr.write = (chunk) => {
		chunks.push(String(chunk));
		return true;
	};
	try {
		fn();
	} finally {
		process.stderr.write = original;
	}
	return chunks.join("");
}

function makeEntry(overrides = {}) {
	const now = new Date().toISOString();
	return {
		id: generateULID(),
		kind: "reminder",
		status: "pending",
		due_at: now,
		created_at: now,
		payload: { message: "test reminder" },
		created_by: "user",
		...overrides,
	};
}

describe("schedule-launch-banner", () => {
	let testDir;
	let originalCwd;

	beforeEach(() => {
		testDir = join(
			tmpdir(),
			`sf-banner-test-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
		);
		mkdirSync(testDir, { recursive: true });
		originalCwd = process.cwd();
		process.chdir(testDir);
	});

	afterEach(() => {
		process.chdir(originalCwd);
		try {
			rmSync(testDir, { recursive: true });
		} catch {
			// ignore
		}
	});

	describe("printScheduleBanner", () => {
		it("is silent when no entries are due", () => {
			const output = captureStderr(() => printScheduleBanner(testDir));
			assert.equal(output, "");
		});

		it("prints a banner for a single due entry", () => {
			const store = createScheduleStore(testDir);
			const entry = makeEntry({
				due_at: "2024-01-01T00:00:00.000Z",
				payload: { message: "Review PR" },
			});
			store.appendEntry("project", entry);

			const output = captureStderr(() => printScheduleBanner(testDir));
			assert.ok(output.includes("1 scheduled item due"));
			assert.ok(output.includes("Review PR"));
			assert.ok(output.includes("Manage: /schedule list"));
		});

		it("prints a banner for multiple due entries", () => {
			const store = createScheduleStore(testDir);
			store.appendEntry(
				"project",
				makeEntry({
					due_at: "2024-01-01T00:00:00.000Z",
					payload: { message: "First" },
				}),
			);
			store.appendEntry(
				"project",
				makeEntry({
					due_at: "2024-01-01T00:00:00.000Z",
					payload: { message: "Second" },
				}),
			);

			const output = captureStderr(() => printScheduleBanner(testDir));
			assert.ok(output.includes("2 scheduled items due"));
			assert.ok(output.includes("First"));
			assert.ok(output.includes("Second"));
		});

		it("labels due autonomous dispatch project entries as autonomous work", () => {
			const store = createScheduleStore(testDir);
			store.appendEntry(
				"project",
				makeEntry({
					kind: "command",
					due_at: "2024-01-01T00:00:00.000Z",
					autonomous_dispatch: true,
					payload: { command: 'node -e "process.exit(0)"' },
				}),
			);

			const output = captureStderr(() => printScheduleBanner(testDir));
			assert.ok(output.includes("1 scheduled autonomous dispatch item due"));
			assert.ok(
				output.includes("autonomous mode will consume project entries"),
			);
			assert.equal(output.includes("Manage: /schedule list"), false);
		});

		it("truncates to 3 titles with a +more suffix", () => {
			const store = createScheduleStore(testDir);
			for (let i = 0; i < 5; i++) {
				store.appendEntry(
					"project",
					makeEntry({
						due_at: "2024-01-01T00:00:00.000Z",
						payload: { message: `Item ${i}` },
					}),
				);
			}

			const output = captureStderr(() => printScheduleBanner(testDir));
			assert.ok(output.includes("(+2 more)"));
		});

		it("does not print done entries", () => {
			const store = createScheduleStore(testDir);
			store.appendEntry(
				"project",
				makeEntry({
					due_at: "2024-01-01T00:00:00.000Z",
					status: "done",
					payload: { message: "Already done" },
				}),
			);

			const output = captureStderr(() => printScheduleBanner(testDir));
			assert.equal(output, "");
		});

		it("does not print future entries", () => {
			const store = createScheduleStore(testDir);
			store.appendEntry(
				"project",
				makeEntry({
					due_at: "2030-01-01T00:00:00.000Z",
					payload: { message: "Future" },
				}),
			);

			const output = captureStderr(() => printScheduleBanner(testDir));
			assert.equal(output, "");
		});
	});

	describe("showScheduleBanner", () => {
		it("is an alias for printScheduleBanner", () => {
			const store = createScheduleStore(testDir);
			store.appendEntry(
				"project",
				makeEntry({
					due_at: "2024-01-01T00:00:00.000Z",
					payload: { message: "Alias test" },
				}),
			);

			const out1 = captureStderr(() => printScheduleBanner(testDir));
			const out2 = captureStderr(() => showScheduleBanner(testDir));
			assert.equal(out1, out2);
		});
	});
});
