/**
 * complete-slice-evidence.test.mjs — slice completion evidence.
 *
 * Purpose: prove slice completion records structured DB evidence in addition
 * to generated SUMMARY/UAT markdown projections.
 */
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 {
	closeDatabase,
	getSlice,
	getSliceAuditTrail,
	insertMilestone,
	insertSlice,
	insertTask,
	openDatabase,
} from "../sf-db.js";
import { handleCompleteSlice } from "../tools/complete-slice.js";

const tmpDirs = [];

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

function makeProject() {
	const dir = mkdtempSync(join(tmpdir(), "sf-complete-slice-evidence-"));
	tmpDirs.push(dir);
	mkdirSync(join(dir, ".sf", "milestones", "M001", "slices", "S01"), {
		recursive: true,
	});
	openDatabase(join(dir, ".sf", "sf.db"));
	insertMilestone({ id: "M001", title: "Evidence", status: "active" });
	insertSlice({
		milestoneId: "M001",
		id: "S01",
		title: "Slice",
		status: "pending",
	});
	insertTask({
		milestoneId: "M001",
		sliceId: "S01",
		id: "T01",
		title: "Task",
		status: "complete",
		// ADR-0000 (SF v70): every task must carry a goal-anchored trace
		// before complete-slice will close the parent slice.
		purposeTrace:
			"Served the slice-goal clause covered by this evidence fixture.",
	});
	return dir;
}

test("handleCompleteSlice_when_successful_records_completion_summary_evidence", async () => {
	const project = makeProject();

	const result = await handleCompleteSlice(
		{
			milestoneId: "M001",
			sliceId: "S01",
			sliceTitle: "Slice",
			verification: "Verification passed.",
			uatContent: "UAT passed.",
			oneLiner: "Slice finished with evidence",
			narrative: "All tasks are closed.",
			successCriteriaResults: "Passed.",
			verificationProof: "Focused test passed.",
			keyDecisions: ["Keep slice evidence in DB"],
			keyFiles: ["src/resources/extensions/sf/tools/complete-slice.js"],
		},
		project,
	);

	assert.equal(result.error, undefined);
	assert.equal(getSlice("M001", "S01").status, "complete");
	const trail = getSliceAuditTrail("M001", "S01");
	assert.equal(trail.length, 1);
	assert.equal(trail[0].evidence_type, "completion_summary");
	assert.match(trail[0].content, /Slice finished with evidence/);
	assert.match(trail[0].content, /Keep slice evidence in DB/);
});

test("handleCompleteSlice_writes_uat_with_UAT_Type_header_so_downstream_can_parse_mode", async () => {
	const project = makeProject();
	const uatPath = join(
		project,
		".sf",
		"milestones",
		"M001",
		"slices",
		"S01",
		"S01-UAT.md",
	);

	const result = await handleCompleteSlice(
		{
			milestoneId: "M001",
			sliceId: "S01",
			sliceTitle: "Slice",
			verification: "Verification passed.",
			uatContent: "UAT passed.",
			oneLiner: "Slice finished with evidence",
			narrative: "All tasks are closed.",
			keyDecisions: [],
			keyFiles: [],
		},
		project,
	);

	assert.equal(result.error, undefined);
	assert.equal(result.uatPath, uatPath);
	const { readFileSync } = await import("node:fs");
	const diskUat = readFileSync(uatPath, "utf8");
	assert.match(
		diskUat,
		/^## UAT Type$/m,
		"UAT.md must contain ## UAT Type section",
	);
	assert.match(diskUat, /- UAT mode: artifact-driven/m);
	assert.match(diskUat, /## UAT Type\n\n- UAT mode: artifact-driven/m);
	const { extractUatType } = await import("../files.js");
	assert.equal(extractUatType(diskUat), "artifact-driven");
});

test("handleCompleteSlice_when_uat_declares_non_artifact_mode_does_not_duplicate_UAT_Type", async () => {
	const project = makeProject();
	const uatPath = join(
		project,
		".sf",
		"milestones",
		"M001",
		"slices",
		"S01",
		"S01-UAT.md",
	);
	const agentBody = `## UAT Type

- UAT mode: browser-executable
- Why this mode is sufficient: Playwright validates the UX flow end-to-end

## Steps

1. Run the headed Playwright smoke and confirm the dashboard renders.`;

	const result = await handleCompleteSlice(
		{
			milestoneId: "M001",
			sliceId: "S01",
			sliceTitle: "Slice",
			verification: "Verification passed.",
			uatContent: agentBody,
			oneLiner: "Slice finished with evidence",
			narrative: "All tasks are closed.",
			keyDecisions: [],
			keyFiles: [],
		},
		project,
	);

	assert.equal(result.error, undefined);
	const { readFileSync } = await import("node:fs");
	const diskUat = readFileSync(uatPath, "utf8");
	assert.equal(
		(diskUat.match(/^## UAT Type$/gm) ?? []).length,
		1,
		"handler must not prepend a second ## UAT Type when the agent already declared one",
	);
	const { extractUatType } = await import("../files.js");
	assert.equal(extractUatType(diskUat), "browser-executable");
});
