import assert from "node:assert/strict";
import { afterEach, describe, it, vi } from "vitest";

import { DynamicBorder } from "./dynamic-border.js";

function makeTUI() {
	return {
		renderCount: 0,
		requestRender() {
			this.renderCount++;
		},
	};
}

describe("DynamicBorder spinner", () => {
	afterEach(() => {
		vi.useRealTimers();
	});

	it("spinner_when_external_renders_are_recent_still_requests_tick_render", () => {
		vi.useFakeTimers();
		const border = new DynamicBorder((s) => s);
		const tui = makeTUI();

		border.startSpinner(tui as any, (s) => s);
		assert.equal(tui.renderCount, 1, "initial render on startSpinner");

		// Simulate an externally triggered render from streaming immediately before
		// the spinner tick. The spinner must still schedule its own redraw so the
		// working indicator does not look frozen during active output.
		border.render(80);
		vi.advanceTimersByTime(200);

		assert.equal(
			tui.renderCount,
			2,
			"spinner tick should request render even after a recent render",
		);

		border.stopSpinner();
	});

	it("spinner_when_no_external_render_occurs_requests_tick_render", () => {
		vi.useFakeTimers();
		const border = new DynamicBorder((s) => s);
		const tui = makeTUI();

		border.startSpinner(tui as any, (s) => s);
		const initialCount = tui.renderCount;

		vi.advanceTimersByTime(200);

		assert.ok(
			tui.renderCount > initialCount,
			"spinner should trigger requestRender when no recent external render",
		);

		border.stopSpinner();
	});
});
