// @crash-shield-ignore-file — config/cache reader for Planu-controlled JSON; writer is this codebase, shape guaranteed by build/seed.
// Planu — bundle-installer.ts
// Installs domain bundle components (skills, rules, spec templates) into a project.
import { readFile, writeFile, mkdir, access } from 'node:fs/promises';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
// ---------------------------------------------------------------------------
// Config loading
// ---------------------------------------------------------------------------
const CONFIG_PATH = join(dirname(fileURLToPath(import.meta.url)), '../config/domain-bundles.json');
let cachedBundles = null;
async function loadBundles() {
    if (cachedBundles !== null) {
        return cachedBundles;
    }
    const raw = await readFile(CONFIG_PATH, 'utf-8');
    const config = JSON.parse(raw);
    cachedBundles = config.bundles;
    return cachedBundles;
}
// ---------------------------------------------------------------------------
// Public API
// ---------------------------------------------------------------------------
/**
 * Returns all available domain bundles (synchronous after first load).
 * Loads config lazily on first call.
 */
export async function listBundlesAsync() {
    return loadBundles();
}
/**
 * Checks if a file exists at the given path.
 */
async function fileExists(filePath) {
    try {
        await access(filePath);
        return true;
    }
    catch {
        return false;
    }
}
/**
 * Writes a file, creating parent directories as needed.
 */
async function writeFileWithDirs(filePath, content) {
    await mkdir(dirname(filePath), { recursive: true });
    await writeFile(filePath, content, 'utf-8');
}
/**
 * Installs a domain bundle into the given project path.
 *
 * - Skills → {projectPath}/.claude/skills/{name}
 * - Rules → {projectPath}/.claude/rules/{filename}
 * - Spec templates → {projectPath}/planu/templates/{name}.md
 *
 * If a file already exists and overwrite is false, it is added to skipped.
 */
export async function installBundle(bundleId, projectPath, options) {
    const overwrite = options.overwrite ?? false;
    const result = {
        bundleId,
        installed: [],
        skipped: [],
        errors: [],
    };
    const bundles = await loadBundles();
    const bundle = bundles.find((b) => b.id === bundleId);
    if (!bundle) {
        result.errors.push(`Bundle "${bundleId}" not found`);
        return result;
    }
    // Install skills
    for (const skill of bundle.components.skills) {
        const skillPath = join(projectPath, '.claude', 'skills', skill.name);
        try {
            if (!overwrite && (await fileExists(skillPath))) {
                result.skipped.push(skillPath);
                continue;
            }
            await writeFileWithDirs(skillPath, skill.content);
            result.installed.push(skillPath);
        }
        catch (err) {
            result.errors.push(`Failed to install skill "${skill.name}": ${String(err)}`);
        }
    }
    // Install rules
    for (const rule of bundle.components.rules) {
        const rulePath = join(projectPath, '.claude', 'rules', rule.filename);
        try {
            if (!overwrite && (await fileExists(rulePath))) {
                result.skipped.push(rulePath);
                continue;
            }
            await writeFileWithDirs(rulePath, rule.content);
            result.installed.push(rulePath);
            /* v8 ignore next 3 */
        }
        catch (err) {
            result.errors.push(`Failed to install rule "${rule.filename}": ${String(err)}`);
        }
    }
    // Install spec templates
    for (const template of bundle.components.specTemplates) {
        const templatePath = join(projectPath, 'planu', 'templates', `${template.name}.md`);
        try {
            if (!overwrite && (await fileExists(templatePath))) {
                result.skipped.push(templatePath);
                continue;
            }
            const content = `# ${template.description}\n`;
            await writeFileWithDirs(templatePath, content);
            result.installed.push(templatePath);
            /* v8 ignore next 3 */
        }
        catch (err) {
            result.errors.push(`Failed to install template "${template.name}": ${String(err)}`);
        }
    }
    return result;
}
//# sourceMappingURL=bundle-installer.js.map