#!/usr/bin/env node
// Copyright (c) 2026 Hellmai Ltd
// SPDX-License-Identifier: AGPL-3.0-only
/**
 * @file lumenflow-uninstall.ts
 * Destructive eject — remove all LumenFlow-generated files from a project
 * (WU-2590).
 *
 * Defaults to dry-run. `--confirm` is required to actually delete. Supports
 * `--keep-history`, `--keep-config`, `--client <name>`, and `--json`.
 *
 * Usage:
 *   pnpm lumenflow:uninstall                  # dry-run
 *   pnpm lumenflow:uninstall --confirm         # actually delete
 *   pnpm lumenflow:uninstall --keep-history --keep-config --confirm
 *   pnpm lumenflow:uninstall --client cursor --confirm
 */
import * as fs from 'node:fs';
import * as path from 'node:path';
import { createWUParser } from '@lumenflow/core';
import { runCLI } from './cli-entry-point.js';
import { getGeneratedFileManifest, filterForUninstall, } from './lumenflow-file-classifier.js';
const LOG_PREFIX = '[lumenflow:uninstall]';
export function parseUninstallOptions() {
    const opts = createWUParser({
        name: 'lumenflow-uninstall',
        description: 'Remove all LumenFlow-generated files from this project. Dry-run by default; pass --confirm to actually delete.',
        options: [
            {
                name: 'confirm',
                flags: '--confirm',
                description: 'Actually delete files. Without this, runs as a dry-run.',
                type: 'boolean',
            },
            {
                name: 'keepHistory',
                flags: '--keep-history',
                description: 'Preserve docs/operations/tasks/wu/ and .lumenflow/stamps/',
                type: 'boolean',
            },
            {
                name: 'keepConfig',
                flags: '--keep-config',
                description: 'Preserve workspace.yaml and .lumenflow/constraints.md',
                type: 'boolean',
            },
            {
                name: 'client',
                flags: '--client <type>',
                description: 'Scope deletion to a single client (default: all)',
            },
            {
                name: 'json',
                flags: '--json',
                description: 'Emit machine-readable JSON output',
                type: 'boolean',
            },
        ],
    });
    return {
        confirm: opts.confirm ?? false,
        keepHistory: opts.keepHistory ?? false,
        keepConfig: opts.keepConfig ?? false,
        client: opts.client,
        json: opts.json ?? false,
    };
}
export function buildUninstallPlan(projectDir, opts) {
    const all = getGeneratedFileManifest(projectDir, { client: opts.client });
    const filtered = filterForUninstall(all, {
        keepHistory: opts.keepHistory,
        keepConfig: opts.keepConfig,
    });
    const toStrip = filtered.filter((f) => f.surgicalStrip);
    const toDelete = filtered.filter((f) => !f.surgicalStrip);
    return { dryRun: !opts.confirm, toDelete, toStrip };
}
/**
 * Surgically strip the LumenFlow-managed hooks section from .claude/settings.json
 * while preserving user content.
 */
export function stripClaudeSettings(abs) {
    if (!fs.existsSync(abs))
        return false;
    try {
        const raw = fs.readFileSync(abs, 'utf-8');
        const parsed = JSON.parse(raw);
        delete parsed.hooks;
        fs.writeFileSync(abs, JSON.stringify(parsed, null, 2) + '\n', 'utf-8');
        return true;
    }
    catch {
        return false;
    }
}
/**
 * Strip the WU-2157 recovery section appended to AGENTS.md by integrateCodexCli.
 */
export function stripAgentsRecovery(abs) {
    if (!fs.existsSync(abs))
        return false;
    const content = fs.readFileSync(abs, 'utf-8');
    const marker = '\n---\n\n## Context Recovery (WU-2157)';
    const idx = content.indexOf(marker);
    if (idx < 0)
        return false;
    fs.writeFileSync(abs, content.slice(0, idx).trimEnd() + '\n', 'utf-8');
    return true;
}
export function executePlan(projectDir, plan) {
    for (const file of plan.toDelete) {
        const abs = path.join(projectDir, file.path);
        if (!fs.existsSync(abs))
            continue;
        const stat = fs.statSync(abs);
        if (stat.isDirectory()) {
            fs.rmSync(abs, { recursive: true, force: true });
        }
        else {
            fs.unlinkSync(abs);
        }
    }
    for (const file of plan.toStrip) {
        const abs = path.join(projectDir, file.path);
        if (file.path.endsWith('settings.json')) {
            stripClaudeSettings(abs);
        }
        else if (file.path === 'AGENTS.md') {
            stripAgentsRecovery(abs);
        }
    }
}
function formatPlan(plan) {
    const lines = [];
    lines.push(plan.dryRun ? `${LOG_PREFIX} DRY-RUN — no files modified.` : `${LOG_PREFIX} Removing files:`);
    if (plan.toDelete.length === 0 && plan.toStrip.length === 0) {
        lines.push(`${LOG_PREFIX} No LumenFlow-generated files found.`);
        return lines.join('\n');
    }
    for (const f of plan.toDelete) {
        lines.push(`  delete  ${f.path}  (${f.category}${f.client ? ` · ${f.client}` : ''})`);
    }
    for (const f of plan.toStrip) {
        lines.push(`  strip   ${f.path}  (${f.category}${f.client ? ` · ${f.client}` : ''})`);
    }
    if (plan.dryRun) {
        lines.push('');
        lines.push(`${LOG_PREFIX} Re-run with --confirm to apply.`);
    }
    else {
        lines.push('');
        lines.push(`${LOG_PREFIX} Restore via: git checkout -- <files>  (or: git revert <commit>  if already committed)`);
    }
    return lines.join('\n');
}
export async function main() {
    const opts = parseUninstallOptions();
    const projectDir = process.cwd();
    const plan = buildUninstallPlan(projectDir, opts);
    if (!plan.dryRun) {
        executePlan(projectDir, plan);
    }
    if (opts.json) {
        process.stdout.write(JSON.stringify(plan, null, 2) + '\n');
        return;
    }
    console.log(formatPlan(plan));
}
if (import.meta.main) {
    void runCLI(main);
}
//# sourceMappingURL=lumenflow-uninstall.js.map