import assert from "node:assert/strict";
import { describe, test } from "vitest";
import { generateRequirementsMd } from "../db-writer.js";
import { parseRequirementsSections } from "../md-importer.js";

describe("generateRequirementsMd", () => {
	test("preserves_full_content_blocks_when_projecting_from_db", () => {
		const fullContent = [
			"### R001 — Doctrine Alignment",
			"- Class: core-capability",
			"- Status: active",
			"- Description: Keep the hand-written block intact.",
			"- Why it matters: Operators curated this text.",
			"- Source: spec",
			"- Primary owning slice: M001/S01",
			"- Supporting slices: none",
			"- Validation: unmapped",
			"- Notes: preserve me",
		].join("\n");

		const markdown = generateRequirementsMd([
			{
				id: "R001",
				class: "core-capability",
				status: "active",
				description: "A stale DB summary must not flatten full_content.",
				why: "DB import preserved the richer block.",
				source: "db",
				primary_owner: "M001/S01",
				supporting_slices: "",
				validation: "",
				notes: "",
				full_content: fullContent,
			},
		]);

		assert.match(markdown, /^# Requirements: Autonomous Self-Healing/m);
		assert.match(markdown, /### R001 — Doctrine Alignment/);
		assert.match(markdown, /- Notes: preserve me/);
		assert.doesNotMatch(markdown, /A stale DB summary/);
	});

	test("normalizes_multiline_fields_for_round_trippable_generated_blocks", () => {
		const markdown = generateRequirementsMd([
			{
				id: "R002",
				class: "operational",
				status: "active",
				description: "Address recurring drift\n\nSource IDs: sf-one, sf-two",
				why: "Threshold reached\nacross multiple runs",
				source: "sf-promoter",
				primary_owner: "",
				supporting_slices: "",
				validation: "",
				notes: "Source IDs: sf-one\nsf-two",
				full_content: "",
			},
		]);

		assert.match(markdown, /### R002 — Address recurring drift$/m);
		assert.doesNotMatch(markdown, /^Source IDs:/m);
		assert.match(
			markdown,
			/- Description: Address recurring drift Source IDs: sf-one, sf-two/,
		);
		assert.match(markdown, /- Primary owning slice: unmapped/);
		assert.match(markdown, /- Unmapped active requirements: 1/);

		const parsed = parseRequirementsSections(markdown);
		assert.equal(parsed.length, 1);
		assert.equal(parsed[0].id, "R002");
		assert.equal(
			parsed[0].description,
			"Address recurring drift Source IDs: sf-one, sf-two",
		);
		assert.equal(parsed[0].primary_owner, "unmapped");
	});

	test("orders_requirements_numerically_and_reports_real_mapping_counts", () => {
		const markdown = generateRequirementsMd([
			{
				id: "R010",
				class: "capability",
				status: "active",
				description: "Later",
				primary_owner: "M010/S01",
			},
			{
				id: "R002",
				class: "capability",
				status: "active",
				description: "Earlier",
				primary_owner: "",
			},
		]);

		assert.ok(markdown.indexOf("### R002") < markdown.indexOf("### R010"));
		assert.match(markdown, /- Active requirements: 2/);
		assert.match(markdown, /- Mapped to slices: 1/);
		assert.match(markdown, /- Unmapped active requirements: 1/);
	});

	test("round_trips_cancelled_requirements", () => {
		const markdown = generateRequirementsMd([
			{
				id: "R069",
				class: "architecture",
				status: "cancelled",
				description: "Superseded daemon requirement.",
				why: "The architecture moved to embedded web daemon ownership.",
				source: "operator-direction",
				primary_owner: "M053/S25",
			},
		]);

		assert.match(markdown, /## Cancelled/);
		const parsed = parseRequirementsSections(markdown);
		assert.equal(parsed.length, 1);
		assert.equal(parsed[0].id, "R069");
		assert.equal(parsed[0].status, "cancelled");
	});

	test("round_trips_terminal_sweeper_statuses", () => {
		const markdown = generateRequirementsMd([
			{
				id: "R070",
				class: "operational",
				status: "resolved",
				description: "Backlog evidence drained.",
			},
			{
				id: "R071",
				class: "architecture",
				status: "superseded",
				description: "Folded into a newer requirement.",
			},
		]);

		assert.match(markdown, /## Resolved/);
		assert.match(markdown, /## Superseded/);
		const parsed = parseRequirementsSections(markdown);
		assert.equal(parsed.length, 2);
		assert.equal(parsed[0].status, "resolved");
		assert.equal(parsed[1].status, "superseded");
	});
});
