/**
 * Minimal YAML frontmatter parser tailored to the prompt workflow files
 * in this directory. Mirrors the subset of YAML that the existing `c-*.md`
 * and `p-*.md` files actually use:
 *
 *   key: value              -> string
 *   key: "quoted value"     -> string (quotes stripped)
 *   key:                    -> block scalar (everything more-indented is
 *                              collected, de-indented, and returned as one
 *                              string with newlines)
 *
 * Comments (`# ...`) and blank lines are skipped. Quoted strings have
 * their quotes stripped, matching the convention used in the rest of the
 * repo (no nested quoting or escapes are needed by the fixtures).
 */
export interface ParsedDoc {
	frontmatter: Record<string, string>;
	body: string;
}

function stripComment(line: string): string {
	const idx = line.indexOf("#");
	// Only treat `#` as a comment when it appears at start-of-line or
	// after whitespace; otherwise the `#` is part of a value (it never
	// is in this repo, but it keeps the parser robust).
	if (idx === -1) return line;
	const before = line.slice(0, idx);
	if (/^\s*$/.test(before)) return before;
	return line;
}

function deIndentBlock(block: string): string {
	const lines = block.split("\n");
	const indents = lines
		.filter((l) => l.trim() !== "")
		.map((l) => l.match(/^[ \t]*/)?.[0].length ?? 0);
	const min = indents.length === 0 ? 0 : Math.min(...indents);
	if (min === 0) return block.replace(/^\n+/, "");
	return lines
		.map((l) => (l.length >= min ? l.slice(min) : l))
		.join("\n")
		.replace(/^\n+/, "");
}

export function parseFrontmatter(content: string): ParsedDoc {
	const normalized = content.replace(/\r\n/g, "\n");
	if (!normalized.startsWith("---")) {
		return { frontmatter: {}, body: normalized };
	}

	// The closing fence is `\n---` (optionally followed by whitespace/eol).
	const endIndex = normalized.indexOf("\n---", 3);
	if (endIndex === -1) {
		return { frontmatter: {}, body: normalized };
	}

	const block = normalized.slice(3, endIndex);
	const body = normalized.slice(endIndex + 4).replace(/^\s+/, "");

	const frontmatter: Record<string, string> = {};
	let currentKey: string | null = null;
	let currentBlock: string[] | null = null;
	let currentIndent = -1;

	const flush = () => {
		if (currentKey === null || currentBlock === null) return;
		frontmatter[currentKey] = deIndentBlock(currentBlock.join("\n"));
		currentKey = null;
		currentBlock = null;
		currentIndent = -1;
	};

	for (const rawLine of block.split("\n")) {
		const line = stripComment(rawLine);
		if (line.trim() === "") {
			// Preserve blank lines inside an open block scalar, otherwise
			// ignore them between keys.
			if (currentBlock !== null) currentBlock.push("");
			continue;
		}

		const indent = line.match(/^[ \t]*/)?.[0].length ?? 0;
		if (currentKey !== null && currentBlock !== null && indent > currentIndent) {
			currentBlock.push(line);
			continue;
		}

		flush();

		const match = line.match(/^([A-Za-z][\w-]*):\s*(.*)$/);
		if (!match) continue;
		const key = match[1];
		const raw = match[2].trim();

		if (raw === "" || raw === ">" || raw === "|-" || raw === ">-" || raw === "|") {
			currentKey = key;
			currentBlock = [];
			currentIndent = indent;
		} else {
			const quoted =
				(raw.startsWith('"') && raw.endsWith('"')) ||
				(raw.startsWith("'") && raw.endsWith("'"));
			frontmatter[key] = quoted ? raw.slice(1, -1) : raw;
		}
	}

	flush();

	return { frontmatter, body };
}

/**
 * Split a `chain:` frontmatter value into individual step names.
 * Mirrors the upstream convention of ` -> ` as the delimiter and trims
 * whitespace from each step.
 */
export function parseChain(value: string | undefined): string[] {
	if (!value) return [];
	return value
		.split(" -> ")
		.map((s) => s.trim())
		.filter((s) => s.length > 0);
}
