// spec-migrator/flatten-specs.ts — Discover and flatten nested spec folders
import { rename, readdir, access, readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { cleanupEmptyDirs, findSpecFiles, convertBlockquoteToFrontmatter, } from './folder-operations.js';
const SPEC_ID_PREFIX_RE = /^SPEC-\d{3,}/;
/** Phase 2: rename unprefixed folders using SPEC ID extracted from spec.md heading. */
async function renameMissingPrefixFolders(specsRoot) {
    let renamedCount = 0;
    try {
        const rootEntries = await readdir(specsRoot, { withFileTypes: true });
        for (const entry of rootEntries) {
            if (!entry.isDirectory() || SPEC_ID_PREFIX_RE.test(entry.name)) {
                continue;
            }
            const specMdPath = join(specsRoot, entry.name, 'spec.md');
            try {
                const content = await readFile(specMdPath, 'utf-8');
                const headingMatch = /^#\s+(SPEC-\d{3,})/.exec(content.replace(/^---[\s\S]*?---\n*/, ''));
                if (!headingMatch?.[1]) {
                    continue;
                }
                const newDir = join(specsRoot, `${headingMatch[1]}-${entry.name}`);
                try {
                    await access(newDir);
                    continue; // Target exists — skip
                }
                catch {
                    /* proceed */
                }
                await rename(join(specsRoot, entry.name), newDir);
                renamedCount++;
            }
            catch {
                /* spec.md unreadable — skip */
            }
        }
    }
    catch {
        /* specsRoot unreadable — skip */
    }
    return renamedCount;
}
/** Process a single nested spec entry: move to root and convert frontmatter. */
async function flattenNestedEntry(specsRoot, category, slug, errors) {
    const srcDir = join(specsRoot, category, slug);
    const destDir = join(specsRoot, slug);
    try {
        await access(destDir);
        errors.push(`skip ${category}/${slug}: destination already exists`);
        return { flattened: false, converted: false };
    }
    catch {
        /* good — destination doesn't exist */
    }
    try {
        await rename(srcDir, destDir);
        await cleanupEmptyDirs(join(specsRoot, category));
        let converted = false;
        try {
            converted = await convertBlockquoteToFrontmatter(join(destDir, 'spec.md'));
        }
        catch {
            /* best-effort */
        }
        return { flattened: true, converted };
    }
    catch (err) {
        errors.push(`flatten ${category}/${slug}: ${err instanceof Error ? err.message : String(err)}`);
        return { flattened: false, converted: false };
    }
}
/**
 * Discover specs buried in subcategory folders and flatten them to planu/specs/{slug}/.
 * Also converts old blockquote metadata to YAML frontmatter.
 * This runs on init_project to fix specs created by older Planu versions.
 */
export async function discoverAndFlattenSpecs(projectPath) {
    const specsRoot = join(projectPath, 'planu/specs');
    const errors = [];
    let flattenedCount = 0;
    let convertedCount = 0;
    const specFiles = await findSpecFiles(specsRoot, specsRoot);
    for (const relPath of specFiles) {
        const parts = relPath.split('/');
        if (parts.length < 2) {
            continue;
        }
        if (parts.length === 2) {
            // Already flat — check for frontmatter conversion
            try {
                if (await convertBlockquoteToFrontmatter(join(specsRoot, relPath))) {
                    convertedCount++;
                }
            }
            catch (err) {
                errors.push(`frontmatter ${relPath}: ${err instanceof Error ? err.message : String(err)}`);
            }
            continue;
        }
        const { flattened, converted } = await flattenNestedEntry(specsRoot, parts[0] ?? '', parts[1] ?? '', errors);
        if (flattened) {
            flattenedCount++;
        }
        if (converted) {
            convertedCount++;
        }
    }
    const renamedCount = await renameMissingPrefixFolders(specsRoot);
    return { flattenedCount, convertedCount, renamedCount, errors };
}
//# sourceMappingURL=flatten-specs.js.map