// spec-migrator/folder-operations.ts — Filesystem helpers for spec migration
import { mkdir, rename, readdir, rmdir, access, readFile } from 'node:fs/promises';
import { atomicWriteFile } from '../safety/atomic-write-file.js';
import { join, dirname } from 'node:path';
export { mkdir, rename, access };
export async function safeReaddir(dir) {
    try {
        return await readdir(dir);
    }
    catch {
        return [];
    }
}
export async function cleanupEmptyDirs(dir) {
    try {
        const entries = await readdir(dir);
        if (entries.length === 0) {
            await rmdir(dir);
            // Try to clean parent too (e.g., docs/sdd/specs/ itself)
            await cleanupEmptyDirs(dirname(dir));
        }
    }
    catch {
        // Directory might not exist or not be empty — safe to ignore
    }
}
/** Recursively find all spec.md files, returning paths relative to root. */
export async function findSpecFiles(dir, root) {
    const results = [];
    try {
        const entries = await readdir(dir, { withFileTypes: true });
        for (const entry of entries) {
            const fullPath = join(dir, entry.name);
            if (entry.isDirectory()) {
                const nested = await findSpecFiles(fullPath, root);
                results.push(...nested);
            }
            else if (entry.name === 'spec.md') {
                const rel = fullPath.slice(root.length + 1); // +1 for trailing /
                results.push(rel);
            }
        }
    }
    catch {
        /* directory unreadable */
    }
    return results;
}
/** Convert old blockquote metadata to YAML frontmatter. Returns true if converted. */
export async function convertBlockquoteToFrontmatter(specMdPath) {
    const content = await readFile(specMdPath, 'utf-8');
    // Already has frontmatter — skip
    if (content.startsWith('---\n')) {
        return false;
    }
    // Detect blockquote metadata pattern:
    // > **Type:** feature | **Scope:** cross-module | **Target:** backend
    // > **Status:** draft | **Difficulty:** 3/5 | **Risk:** medium
    const blockquoteRe = /^#\s+(?:SPEC-\d+:\s*)?(.+)\n\n(?:>\s+\*\*\w+:\*\*[^\n]+\n)+/;
    const match = blockquoteRe.exec(content);
    if (!match) {
        return false;
    }
    const title = match[1]?.trim() ?? '';
    const blockquoteBlock = match[0];
    // Extract fields from blockquote lines
    const fields = {};
    const fieldRe = /\*\*(\w+):\*\*\s*([^|*]+)/g;
    let fm;
    while ((fm = fieldRe.exec(blockquoteBlock)) !== null) {
        const key = (fm[1] ?? '').toLowerCase().trim();
        const val = (fm[2] ?? '').trim();
        if (key && val) {
            fields[key] = val;
        }
    }
    // Build YAML frontmatter
    const yamlLines = ['---'];
    if (title) {
        yamlLines.push(`title: "${title.replace(/"/g, '\\"')}"`);
    }
    if (fields.type) {
        yamlLines.push(`type: ${fields.type}`);
    }
    if (fields.scope) {
        yamlLines.push(`scope: ${fields.scope}`);
    }
    if (fields.target) {
        yamlLines.push(`target: ${fields.target}`);
    }
    if (fields.status) {
        yamlLines.push(`status: ${fields.status}`);
    }
    if (fields.difficulty) {
        yamlLines.push(`difficulty: ${fields.difficulty}`);
    }
    if (fields.risk) {
        yamlLines.push(`risk: ${fields.risk}`);
    }
    yamlLines.push('---');
    yamlLines.push('');
    // Replace blockquote header with frontmatter + clean title
    const rest = content.slice(blockquoteBlock.length);
    const specIdMatch = /^#\s+(SPEC-\d+)/.exec(content);
    const heading = specIdMatch ? `# ${specIdMatch[1]}: ${title}` : `# ${title}`;
    const newContent = yamlLines.join('\n') + heading + '\n' + rest;
    await atomicWriteFile(specMdPath, newContent);
    return true;
}
//# sourceMappingURL=folder-operations.js.map