import assert from "node:assert/strict";
import { existsSync, mkdtempSync, readFileSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, test } from "vitest";
import {
	STATUS_PROJECTION_FILE,
	buildStatusProjection,
	writeStatusProjection,
} from "../status-projection.js";
import type { QuerySnapshot } from "../headless-query.js";

const roots: string[] = [];

afterEach(() => {
	for (const root of roots.splice(0)) {
		rmSync(root, { recursive: true, force: true });
	}
});

function makeRoot() {
	const root = mkdtempSync(join(tmpdir(), "sf-status-projection-"));
	roots.push(root);
	return root;
}

function snapshot(): QuerySnapshot {
	return {
		schemaVersion: 1,
		state: {
			activeMilestone: { id: "M053", title: "Supervisor" },
			activeSlice: { id: "S11", title: "Web projection" },
			activeTask: null,
			phase: "planning",
			recentDecisions: [],
			blockers: [],
			nextAction: "Plan projection",
			registry: [{ id: "M054", title: "Later", status: "pending" }],
			requirements: {
				active: 1,
				validated: 0,
				deferred: 0,
				outOfScope: 0,
				blocked: 0,
				total: 1,
			},
			progress: {
				milestones: { done: 0, total: 1 },
				slices: { done: 0, total: 1 },
			},
		} as QuerySnapshot["state"],
		next: { action: "dispatch", unitType: "plan-slice", unitId: "M053/S11" },
		cost: { workers: [], total: 0 },
		runtime: { units: [] },
		uokDiagnostics: {
			verdict: "clear",
			classification: "running",
			currentUnit: { unitType: "plan-slice", unitId: "M053/S11", pid: 123 },
			latestRun: { status: "started" },
			issues: [],
		},
	};
}

describe("status projection", () => {
	test("buildStatusProjection_from_query_snapshot_returns_read_model", () => {
		const root = makeRoot();
		const projection = buildStatusProjection(root, snapshot());

		assert.equal(projection.projectionVersion, 1);
		assert.equal(projection.state.activeMilestoneId, "M053");
		assert.equal(projection.state.currentUnit, "plan-slice:M053/S11");
		assert.equal(projection.state.queueDepth, 1);
		assert.equal(projection.supervisor.health, "running");
		assert.equal(projection.supervisor.currentPid, 123);
	});

	test("writeStatusProjection_writes_atomic_projection_file", () => {
		const root = makeRoot();
		const projection = writeStatusProjection(root, snapshot());
		const path = join(root, ".sf", STATUS_PROJECTION_FILE);

		assert.equal(existsSync(path), true);
		const parsed = JSON.parse(readFileSync(path, "utf-8"));
		assert.equal(parsed.projectionVersion, projection.projectionVersion);
		assert.equal(parsed.state.activeSliceId, "S11");
	});
});
