/**
 * auto-prompts-phase3.test.mjs — Phase 3 v2 builder migration contracts.
 *
 * Purpose: prove that the composeUnitContext v2 migration of plan-milestone,
 * validate-milestone, complete-milestone, replan-slice, and research-slice
 * produces prompts containing the expected artifact sections and does not
 * regress the ordering or content of prior implementations.
 */
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { afterEach, describe, expect, test } from "vitest";
import * as AutoPrompts from "../auto-prompts.js";
import {
	closeDatabase,
	insertMilestone,
	insertSlice,
	insertTask,
	openDatabase,
} from "../sf-db.js";

let tempDirs = [];

function makeProject(opts = {}) {
	const dir = mkdtempSync(join(tmpdir(), "sf-phase3-prompts-"));
	tempDirs.push(dir);
	const mid = opts.mid ?? "M910";
	const sid = opts.sid ?? "S01";
	mkdirSync(join(dir, ".sf", "milestones", mid, "slices", sid, "tasks"), {
		recursive: true,
	});
	writeFileSync(
		join(dir, ".sf", "milestones", mid, `${mid}-ROADMAP.md`),
		`# ${mid}: Test Milestone\n\n## ${sid}: Test Slice\n`,
	);
	writeFileSync(
		join(dir, ".sf", "milestones", mid, `${mid}-CONTEXT.md`),
		`# Context\n\nMilestone context for testing.\n`,
	);
	writeFileSync(
		join(dir, ".sf", "milestones", mid, "slices", sid, `${sid}-CONTEXT.md`),
		`# Slice Context\n\nSlice context for testing.\n`,
	);
	writeFileSync(
		join(dir, ".sf", "milestones", mid, "slices", sid, `${sid}-PLAN.md`),
		`# ${sid}: Test Slice\n\n## Tasks\n\n- T01: Do the thing\n`,
	);
	return { dir, mid, sid };
}

afterEach(() => {
	closeDatabase();
	for (const dir of tempDirs) {
		rmSync(dir, { recursive: true, force: true });
	}
	tempDirs = [];
});

describe("buildPlanMilestonePrompt v2", () => {
	test("plan_milestone_prompt_inlines_context_and_templates_at_standard_level", async () => {
		const { dir, mid } = makeProject({ mid: "M910" });
		openDatabase(join(dir, ".sf", "sf.db"));
		insertMilestone({
			id: mid,
			title: "Test Milestone",
			status: "active",
			planning: { vision: "Test.", successCriteria: [] },
		});

		const prompt = await AutoPrompts.buildPlanMilestonePrompt(
			mid,
			"Test Milestone",
			dir,
			"standard",
		);

		expect(prompt).toContain("Milestone Context");
		expect(prompt).toContain("## Inlined Context");
		// Standard level includes roadmap template
		expect(prompt).toContain("Roadmap");
		// Standard level includes plan template
		expect(prompt).toContain("Slice Plan");
	});

	test("plan_milestone_prompt_omits_db_artifacts_at_minimal_level", async () => {
		const { dir, mid } = makeProject({ mid: "M911" });
		openDatabase(join(dir, ".sf", "sf.db"));
		insertMilestone({
			id: mid,
			title: "Minimal Milestone",
			status: "active",
			planning: { vision: "Test.", successCriteria: [] },
		});

		const prompt = await AutoPrompts.buildPlanMilestonePrompt(
			mid,
			"Minimal Milestone",
			dir,
			"minimal",
		);

		expect(prompt).toContain("## Inlined Context");
		// Minimal level skips project/requirements/decisions DB reads
		// Still inlines context file
		expect(prompt).toContain("Milestone Context");
	});

	test("plan_milestone_prompt_inlines_queue_file_when_present", async () => {
		const { dir, mid } = makeProject({ mid: "M912" });
		openDatabase(join(dir, ".sf", "sf.db"));
		insertMilestone({
			id: mid,
			title: "Queue Milestone",
			status: "active",
			planning: { vision: "Test.", successCriteria: [] },
		});
		mkdirSync(join(dir, ".sf"), { recursive: true });
		writeFileSync(join(dir, ".sf", "QUEUE.md"), "M912 — next in queue\n");

		const prompt = await AutoPrompts.buildPlanMilestonePrompt(
			mid,
			"Queue Milestone",
			dir,
			"minimal",
		);

		expect(prompt).toContain("Project Queue");
	});
});

describe("buildReplanSlicePrompt v2", () => {
	test("replan_slice_prompt_includes_roadmap_and_slice_plan", async () => {
		const { dir, mid, sid } = makeProject({ mid: "M920", sid: "S01" });
		openDatabase(join(dir, ".sf", "sf.db"));
		insertMilestone({
			id: mid,
			title: "Replan Milestone",
			status: "active",
			planning: { vision: "Test.", successCriteria: [] },
		});
		insertSlice({
			milestoneId: mid,
			id: sid,
			title: "Test Slice",
			status: "active",
			risk: "low",
			depends: [],
			demo: "Done.",
			sequence: 1,
		});

		const prompt = await AutoPrompts.buildReplanSlicePrompt(
			mid,
			"Replan Milestone",
			sid,
			"Test Slice",
			dir,
		);

		expect(prompt).toContain("## Inlined Context");
		expect(prompt).toContain("Milestone Roadmap");
		expect(prompt).toContain("Current Slice Plan");
	});

	test("replan_slice_prompt_includes_blocker_summaries_when_present", async () => {
		const { dir, mid, sid } = makeProject({ mid: "M921", sid: "S01" });
		openDatabase(join(dir, ".sf", "sf.db"));
		insertMilestone({
			id: mid,
			title: "Blocker Milestone",
			status: "active",
			planning: { vision: "Test.", successCriteria: [] },
		});
		insertSlice({
			milestoneId: mid,
			id: sid,
			title: "Blocked Slice",
			status: "active",
			risk: "high",
			depends: [],
			demo: "Unblocked.",
			sequence: 1,
		});
		// Write a task summary with blocker_discovered: true
		writeFileSync(
			join(
				dir,
				".sf",
				"milestones",
				mid,
				"slices",
				sid,
				"tasks",
				"T01-SUMMARY.md",
			),
			"---\nblocker_discovered: true\nid: T01\n---\n# T01 Summary\n\nBlocked by external API.\n",
		);

		const prompt = await AutoPrompts.buildReplanSlicePrompt(
			mid,
			"Blocker Milestone",
			sid,
			"Blocked Slice",
			dir,
		);

		expect(prompt).toContain("Blocker Task Summary");
	});
});

describe("buildValidateMilestonePrompt v2", () => {
	test("validate_milestone_prompt_includes_roadmap_and_gate_block", async () => {
		const { dir, mid, sid } = makeProject({ mid: "M930", sid: "S01" });
		openDatabase(join(dir, ".sf", "sf.db"));
		insertMilestone({
			id: mid,
			title: "Validate Milestone",
			status: "active",
			planning: { vision: "Test.", successCriteria: [] },
		});
		insertSlice({
			milestoneId: mid,
			id: sid,
			title: "Completed Slice",
			status: "complete",
			risk: "low",
			depends: [],
			demo: "Done.",
			sequence: 1,
		});
		writeFileSync(
			join(dir, ".sf", "milestones", mid, `${mid}-SUMMARY.md`),
			"# M930 Summary\n\nMilestone done.\n",
		);

		const prompt = await AutoPrompts.buildValidateMilestonePrompt(
			mid,
			"Validate Milestone",
			dir,
			"minimal",
		);

		expect(prompt).toContain("## Inlined Context");
		// Gate block must always be present per the milestone validation contract
		expect(prompt).toContain("MV0");
	});
});

describe("buildResearchSlicePrompt v2", () => {
	test("research_slice_prompt_includes_roadmap_and_slice_context", async () => {
		const { dir, mid, sid } = makeProject({ mid: "M940", sid: "S01" });
		openDatabase(join(dir, ".sf", "sf.db"));
		insertMilestone({
			id: mid,
			title: "Research Milestone",
			status: "active",
			planning: { vision: "Test.", successCriteria: [] },
		});
		insertSlice({
			milestoneId: mid,
			id: sid,
			title: "Research Slice",
			status: "active",
			risk: "low",
			depends: [],
			demo: "Research done.",
			sequence: 1,
		});

		const prompt = await AutoPrompts.buildResearchSlicePrompt(
			mid,
			"Research Milestone",
			sid,
			"Research Slice",
			dir,
		);

		expect(prompt).toContain("## Inlined Context");
		expect(prompt).toContain("Milestone Roadmap");
	});
});
