// spec-migrator/legacy-migration.ts — Migrate legacy docs/sdd/specs → planu/specs
import { isLegacyLocation, createPlanuConfig, serializePlanuConfig, } from '../planu-config-writer.js';
import { mkdir, rename } from 'node:fs/promises';
import { atomicWriteFile } from '../safety/atomic-write-file.js';
import { join, dirname } from 'node:path';
import { rewritePath, flattenSpecPath, LEGACY_TO_MODERN_NAMES } from './path-utils.js';
import { safeReaddir, cleanupEmptyDirs } from './folder-operations.js';
/**
 * Detect specs stored under a legacy location (docs/sdd/specs/).
 * Caller provides the list of specs (from storage layer).
 */
export function filterLegacySpecs(specs) {
    return specs.filter((s) => isLegacyLocation(s.specPath) || isLegacyLocation(s.technicalPath));
}
/**
 * Migrate legacy specs to planu/specs/ with modern file naming.
 * Moves files on disk and calls the provided updateSpec for each migrated spec.
 * Also rewrites planu.json.
 */
export async function migrateSpecs(projectPath, legacySpecs, deps) {
    const errors = [];
    let migratedCount = 0;
    for (const spec of legacySpecs) {
        try {
            await migrateSingleSpec(projectPath, spec, deps);
            migratedCount++;
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            errors.push(`${spec.id}: ${msg}`);
        }
    }
    // Rewrite planu.json with modern config
    const planuConfigPath = join(projectPath, 'planu.json');
    const planuConfig = createPlanuConfig();
    await atomicWriteFile(planuConfigPath, serializePlanuConfig(planuConfig));
    return { migratedCount, errors };
}
async function migrateSingleSpec(projectPath, spec, deps) {
    const oldSpecDir = dirname(join(projectPath, spec.specPath));
    // Flatten: remove any subcategory between planu/specs/ and the spec folder.
    // Legacy: docs/sdd/specs/{category}/{slug}/spec.md -> planu/specs/{slug}/spec.md
    const newRelDir = flattenSpecPath(spec.specPath.replace(/docs\/sdd\/specs/, 'planu/specs').replace(/\/[^/]+$/, ''));
    const newAbsDir = join(projectPath, newRelDir);
    // Create target directory
    await mkdir(newAbsDir, { recursive: true });
    // Move and rename known files
    const dirEntries = await safeReaddir(oldSpecDir);
    for (const entry of dirEntries) {
        const modernName = LEGACY_TO_MODERN_NAMES[entry] ?? entry;
        const src = join(oldSpecDir, entry);
        const dest = join(newAbsDir, modernName);
        await rename(src, dest);
    }
    // Update spec paths in storage
    const updates = {
        specPath: rewritePath(spec.specPath),
        technicalPath: rewritePath(spec.technicalPath),
    };
    if (spec.progressPath) {
        updates.progressPath = rewritePath(spec.progressPath);
    }
    if (spec.executiveReportPath) {
        updates.executiveReportPath = rewritePath(spec.executiveReportPath);
    }
    if (spec.technicalReportPath) {
        updates.technicalReportPath = rewritePath(spec.technicalReportPath);
    }
    if (spec.planPath) {
        updates.planPath = rewritePath(spec.planPath);
    }
    try {
        await deps.updateSpec(spec.projectId, spec.id, updates);
    }
    catch (err) {
        // Rollback: rename directory back to original location
        try {
            await rename(newAbsDir, oldSpecDir);
        }
        catch {
            /* ignore rollback error */
        }
        throw err;
    }
    // Cleanup empty legacy directories
    await cleanupEmptyDirs(oldSpecDir);
}
//# sourceMappingURL=legacy-migration.js.map