import assert from "node:assert/strict";
import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { test } from 'vitest';

import { verifyExpectedArtifact } from "../auto-recovery.ts";

function createFixtureBase(): string {
	const base = mkdtempSync(join(tmpdir(), "sf-plan-milestone-artifact-"));
	mkdirSync(join(base, ".sf", "milestones"), { recursive: true });
	return base;
}

function writeRoadmap(
	base: string,
	milestoneId: string,
	content: string,
): void {
	const milestoneDir = join(base, ".sf", "milestones", milestoneId);
	mkdirSync(milestoneDir, { recursive: true });
	writeFileSync(
		join(milestoneDir, `${milestoneId}-ROADMAP.md`),
		content,
		"utf-8",
	);
}

test("#3405: plan-milestone roadmap stub does not count as a verified artifact", () => {
	const base = createFixtureBase();
	try {
		writeRoadmap(
			base,
			"M001",
			[
				"# M001: Placeholder",
				"",
				"**Vision:** Stub only.",
				"",
				"## Slices",
				"",
				"_TBD_",
				"",
			].join("\n"),
		);

		const result = verifyExpectedArtifact("plan-milestone", "M001", base);
		assert.equal(
			result,
			false,
			"zero-slice roadmap stubs must fail verification",
		);
	} finally {
		rmSync(base, { recursive: true, force: true });
	}
});

test("plan-milestone roadmap without a vision alignment meeting does not count as a verified artifact", () => {
	const base = createFixtureBase();
	try {
		writeRoadmap(
			base,
			"M001",
			[
				"# M001: Missing ceremony",
				"",
				"## Vision",
				"Real work, but no meeting contract.",
				"",
				"## Slice Overview",
				"| ID | Slice | Risk | Depends | Done | After this |",
				"|----|-------|------|---------|------|------------|",
				"| S01 | First slice | low | — | ⬜ | a real slice exists. |",
				"",
			].join("\n"),
		);

		const result = verifyExpectedArtifact("plan-milestone", "M001", base);
		assert.equal(
			result,
			false,
			"roadmaps missing the vision meeting must fail verification",
		);
	} finally {
		rmSync(base, { recursive: true, force: true });
	}
});

test("#3405: plan-milestone roadmap with real slices still passes artifact verification", () => {
	const base = createFixtureBase();
	try {
		writeRoadmap(
			base,
			"M001",
			[
				"# M001: Real roadmap",
				"",
				"## Vision",
				"Real work.",
				"",
				"## Vision Alignment Meeting",
				"",
				"### Trigger",
				"Need a top-level roadmap synthesis.",
				"",
				"### Product Manager",
				"Ship the smallest credible milestone.",
				"",
				"### User Advocate",
				"Keep the roadmap understandable.",
				"",
				"### Customer Panel",
				"Advanced users want fidelity; maintainers want consistency.",
				"",
				"### Business",
				"This should create a credible planning surface.",
				"",
				"### Researcher",
				"Comparable systems treat roadmap coherence as table stakes.",
				"",
				"### Delivery Lead",
				"Keep milestone one narrow.",
				"",
				"### Partner",
				"The roadmap is right-sized.",
				"",
				"### Combatant",
				"Avoid speculative automation.",
				"",
				"### Architect",
				"Persist and render the meeting.",
				"",
				"### Moderator",
				"Weighted synthesis says this is ready to plan.",
				"",
				"### Weighted Synthesis",
				"This milestone is ready.",
				"",
				"### Confidence By Area",
				"- User need: high",
				"- Sequencing confidence: high",
				"",
				"### Recommended Route",
				"**planning**",
				"",
				"The route is planning because no concrete safety blocker remains.",
				"",
				"## Slice Overview",
				"| ID | Slice | Risk | Depends | Done | After this |",
				"|----|-------|------|---------|------|------------|",
				"| S01 | First slice | low | — | ⬜ | a real slice exists. |",
				"",
			].join("\n"),
		);

		const result = verifyExpectedArtifact("plan-milestone", "M001", base);
		assert.equal(
			result,
			true,
			"real roadmap slices should keep passing verification",
		);
	} finally {
		rmSync(base, { recursive: true, force: true });
	}
});

test("roadmap-meeting uses the same verified roadmap artifact as plan-milestone", () => {
	const base = createFixtureBase();
	try {
		writeRoadmap(
			base,
			"M001",
			[
				"# M001: Initial roadmap",
				"",
				"## Vision",
				"Real work.",
				"",
				"## Vision Alignment Meeting",
				"",
				"### Trigger",
				"Need an initial roadmap meeting.",
				"",
				"### Product Manager",
				"Ship the smallest credible milestone.",
				"",
				"### User Advocate",
				"Keep the roadmap understandable.",
				"",
				"### Customer Panel",
				"Advanced users want fidelity; maintainers want consistency.",
				"",
				"### Business",
				"This should create a credible planning surface.",
				"",
				"### Researcher",
				"Comparable systems treat roadmap coherence as table stakes.",
				"",
				"### Delivery Lead",
				"Keep milestone one narrow.",
				"",
				"### Partner",
				"The roadmap is right-sized.",
				"",
				"### Combatant",
				"Avoid speculative automation.",
				"",
				"### Architect",
				"Persist and render the meeting.",
				"",
				"### Moderator",
				"Weighted synthesis says this is ready to plan.",
				"",
				"### Weighted Synthesis",
				"This milestone is ready.",
				"",
				"### Confidence By Area",
				"- User need: high",
				"- Sequencing confidence: high",
				"",
				"### Recommended Route",
				"planning",
				"",
				"## Slice Overview",
				"| ID | Slice | Risk | Depends | Done | After this |",
				"|----|-------|------|---------|------|------------|",
				"| S01 | First slice | low | — | ⬜ | a real slice exists. |",
				"",
			].join("\n"),
		);

		const result = verifyExpectedArtifact("roadmap-meeting", "M001", base);
		assert.equal(
			result,
			true,
			"roadmap-meeting should verify M001-ROADMAP.md instead of blocking forever",
		);
	} finally {
		rmSync(base, { recursive: true, force: true });
	}
});

test("plan-milestone roadmap routed back to research does not count as a verified artifact", () => {
	const base = createFixtureBase();
	try {
		writeRoadmap(
			base,
			"M001",
			[
				"# M001: Research draft",
				"",
				"## Vision",
				"Real work.",
				"",
				"## Vision Alignment Meeting",
				"",
				"### Trigger",
				"Need a top-level roadmap synthesis.",
				"",
				"### Product Manager",
				"Ship the smallest credible milestone.",
				"",
				"### User Advocate",
				"Keep the roadmap understandable.",
				"",
				"### Customer Panel",
				"Advanced users want fidelity; maintainers want consistency.",
				"",
				"### Business",
				"This should create a credible planning surface.",
				"",
				"### Researcher",
				"Comparable systems are still unclear.",
				"",
				"### Delivery Lead",
				"Keep milestone one narrow.",
				"",
				"### Partner",
				"There is a plausible roadmap.",
				"",
				"### Combatant",
				"Market expectations are not grounded enough yet.",
				"",
				"### Architect",
				"Do not start execution on a weak roadmap.",
				"",
				"### Moderator",
				"Weighted synthesis says keep researching.",
				"",
				"### Weighted Synthesis",
				"The roadmap is still a draft.",
				"",
				"### Confidence By Area",
				"- User need: high",
				"- Comparable-system fit: low",
				"",
				"### Recommended Route",
				"researching",
				"",
				"## Slice Overview",
				"| ID | Slice | Risk | Depends | Done | After this |",
				"|----|-------|------|---------|------|------------|",
				"| S01 | First slice | low | — | ⬜ | a real slice exists. |",
				"",
			].join("\n"),
		);

		const result = verifyExpectedArtifact("plan-milestone", "M001", base);
		assert.equal(
			result,
			false,
			"roadmaps routed back to research must fail verification",
		);
	} finally {
		rmSync(base, { recursive: true, force: true });
	}
});
