/**
 * doctor-purpose-gate.test.mjs — doctor catches DB planning records that lack purpose.
 *
 * Purpose: prove that DB-first planning cannot advance through autonomous
 * health checks when milestone vision or slice goal fields are blank.
 */
import assert from "node:assert/strict";
import { mkdirSync, mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, test } from "vitest";
import { checkEngineHealth } from "../doctor-engine-checks.js";
import {
	closeDatabase,
	insertMilestone,
	insertSlice,
	openDatabase,
} from "../sf-db.js";

const tmpDirs = [];

function makeProject() {
	const dir = mkdtempSync(join(tmpdir(), "sf-purpose-gate-"));
	tmpDirs.push(dir);
	mkdirSync(join(dir, ".sf"), { recursive: true });
	openDatabase(join(dir, ".sf", "sf.db"));
	return dir;
}

afterEach(() => {
	closeDatabase();
	while (tmpDirs.length > 0) {
		const dir = tmpDirs.pop();
		if (dir) rmSync(dir, { recursive: true, force: true });
	}
});

test("checkEngineHealth_when_milestone_vision_is_blank_reports_purpose_error", async () => {
	const dir = makeProject();
	insertMilestone({
		id: "M001",
		title: "Missing purpose milestone",
		status: "active",
		planning: { vision: "   " },
	});
	closeDatabase();
	const issues = [];

	await checkEngineHealth(dir, issues, [], () => false);

	assert.deepEqual(
		issues
			.filter((issue) => issue.code === "db_milestone_missing_vision")
			.map((issue) => [issue.scope, issue.unitId]),
		[["milestone", "M001"]],
	);
});

test("checkEngineHealth_when_slice_goal_is_blank_reports_purpose_error", async () => {
	const dir = makeProject();
	insertMilestone({
		id: "M001",
		title: "Purposeful milestone",
		status: "active",
		planning: { vision: "Protect DB-backed planning purpose gates." },
	});
	insertSlice({
		milestoneId: "M001",
		id: "S01",
		title: "Missing purpose slice",
		status: "active",
		sequence: 1,
		planning: { goal: "   " },
	});
	closeDatabase();
	const issues = [];

	await checkEngineHealth(dir, issues, [], () => false);

	assert.deepEqual(
		issues
			.filter((issue) => issue.code === "db_slice_missing_goal")
			.map((issue) => [issue.scope, issue.unitId]),
		[["slice", "M001/S01"]],
	);
});
