import { execFile } from 'node:child_process';
import { rm } from 'node:fs/promises';
import { buildCommandContext } from '../../../app/command-context.js';
import { withScopeOption } from '../../shared/scope-option.js';
import { readGlobalOptions, resolveConcreteScopes, } from '../../shared/shared.utils.js';
import { autoSync, } from '../../tools/shared/auto-sync.js';
import { scanTools } from '../../tools/shared/scan-tools.js';
import { readOatConfig, writeOatConfig } from '../../../config/oat-config.js';
import { resolveAssetsRoot } from '../../../fs/assets.js';
import { resolveProjectRoot, resolveScopeRoot } from '../../../fs/paths.js';
import { Command } from 'commander';
import { removeTools, } from './remove-tools.js';
const defaultDependencies = {
    scanTools,
    resolveScopeRoot: async (scope, cwd, home) => {
        if (scope === 'project')
            return resolveProjectRoot(cwd);
        return resolveScopeRoot(scope, cwd, home);
    },
    resolveAssetsRoot,
    removeDirectory: async (path) => {
        await rm(path, { recursive: true, force: true });
    },
    removeFile: async (path) => {
        await rm(path, { force: true });
    },
};
const defaultSyncDependencies = {
    runSync: async ({ scope, cwd }) => {
        await new Promise((resolve, reject) => {
            execFile(process.execPath, [...process.execArgv, process.argv[1], 'sync', '--scope', scope], { cwd }, (error) => {
                if (error)
                    reject(error);
                else
                    resolve();
            });
        });
    },
};
const VALID_PACKS = [
    'core',
    'ideas',
    'docs',
    'workflows',
    'utility',
    'project-management',
    'research',
    'brainstorm',
];
export function createToolsRemoveCommand(dependencies = defaultDependencies, syncDependencies = defaultSyncDependencies) {
    return withScopeOption(new Command('remove'))
        .description('Remove installed tools')
        .argument('[name]', 'Tool name to remove')
        .option('--pack <pack>', 'Remove all tools in a pack (core|ideas|docs|workflows|utility|project-management|research|brainstorm)')
        .option('--all', 'Remove all installed tools')
        .option('--dry-run', 'Preview removals without applying')
        .option('--no-sync', 'Skip auto-sync after removal')
        .action(async (name, opts, command) => {
        const globalOptions = readGlobalOptions(command);
        const context = buildCommandContext(globalOptions);
        const { logger } = context;
        const target = resolveTarget(name, opts.pack, opts.all);
        if (!target) {
            logger.error('Specify a tool name, --pack <pack>, or --all.');
            process.exitCode = 1;
            return;
        }
        const scopes = resolveConcreteScopes(context.scope);
        const dryRun = opts.dryRun ?? false;
        const result = await removeTools(target, scopes, context.cwd, context.home, dryRun, dependencies);
        if (!dryRun && result.removed.length > 0) {
            const assetsRoot = await dependencies.resolveAssetsRoot();
            const repoRoot = await resolveProjectRoot(context.cwd);
            const config = await readOatConfig(repoRoot);
            const installedPacks = new Set();
            const configScopes = resolveConcreteScopes('all');
            for (const scope of configScopes) {
                const scopeRoot = await dependencies.resolveScopeRoot(scope, context.cwd, context.home);
                const tools = await dependencies.scanTools({
                    scope,
                    scopeRoot,
                    assetsRoot,
                });
                for (const tool of tools) {
                    if (tool.pack !== 'custom') {
                        installedPacks.add(tool.pack);
                    }
                }
            }
            await writeOatConfig(repoRoot, {
                ...config,
                tools: Object.fromEntries(VALID_PACKS.map((pack) => [pack, installedPacks.has(pack)])),
            });
        }
        if (result.notInstalled.length > 0) {
            if (context.json) {
                logger.json({ target: describeTarget(target), dryRun, result });
            }
            else {
                logger.error(`Tool '${result.notInstalled[0]}' not found.`);
            }
            process.exitCode = 1;
            return;
        }
        // Auto-sync after mutations (before output so sync errors are captured)
        if (result.removed.length > 0 && !dryRun && opts.sync !== false) {
            const affectedScopes = [...new Set(result.removed.map((t) => t.scope))];
            await autoSync(affectedScopes, context.cwd, context.home, logger, syncDependencies);
        }
        if (context.json) {
            logger.json({ target: describeTarget(target), dryRun, result });
            return;
        }
        if (result.removed.length > 0) {
            const verb = dryRun ? 'Would remove' : 'Removed';
            for (const tool of result.removed) {
                logger.success(`${verb}: ${tool.name} (${tool.scope})`);
            }
        }
        else {
            logger.info('No tools to remove.');
        }
    });
}
function resolveTarget(name, pack, all) {
    const specified = [name, pack, all].filter(Boolean).length;
    if (specified !== 1)
        return null;
    if (name)
        return { kind: 'name', name };
    if (pack) {
        if (!VALID_PACKS.includes(pack))
            return null;
        return { kind: 'pack', pack: pack };
    }
    if (all)
        return { kind: 'all' };
    return null;
}
function describeTarget(target) {
    switch (target.kind) {
        case 'name':
            return target.name;
        case 'pack':
            return `pack:${target.pack}`;
        case 'all':
            return 'all';
    }
}
