// tools/install-plugins.ts — MCP tool handler for install_plugins (SPEC-596)
//
// Registers the official Anthropic Claude Code plugin marketplace and
// installs recommended plugins based on the detected project stack.
// Idempotent, stack-aware, opt-in. Never crashes on missing `claude` CLI.
import { knowledgeStore, hashProjectPath } from '../storage/index.js';
import { ensureAnthropicMarketplaceRegistered, getRecommendedForStack, matchStackSignals, scanProjectForStack, installPlugins, } from '../engine/plugin-installer/index.js';
import { emitAutopilotEvent } from '../engine/autopilot/event-bus.js';
/**
 * Core handler — can be called standalone or from init_project scaffold.
 */
export async function handleInstallPlugins(input) {
    const { projectPath, mode, stackHint, dryRun = false } = input;
    try {
        // Resolve stack signals from stored knowledge + any user-provided hints
        const projectId = hashProjectPath(projectPath);
        const knowledge = await knowledgeStore.getKnowledge(projectId).catch(() => null);
        const stackItems = knowledge?.stack ?? [];
        let signals = matchStackSignals(stackItems, stackHint);
        // SPEC-605: fallback — auto-detect stack from package.json when no signals found
        if (signals.length === 0 && (stackHint === undefined || stackHint.length === 0)) {
            signals = await scanProjectForStack(projectPath);
        }
        // Get recommended plugins for the detected stack and mode
        const recommended = await getRecommendedForStack(signals, mode);
        // Register marketplace (idempotent — checks before acting)
        const marketplaceStatus = await ensureAnthropicMarketplaceRegistered(dryRun);
        // Install plugins (idempotent — skips already-installed ones)
        const outcome = await installPlugins(recommended, dryRun);
        const result = {
            projectPath,
            mode,
            dryRun,
            marketplaceAdded: marketplaceStatus.registered,
            installed: outcome.installed,
            skipped: outcome.skipped,
            failed: outcome.failed,
            message: buildMessage({
                dryRun,
                mode,
                marketplaceStatus,
                installed: outcome.installed,
                skipped: outcome.skipped,
                failed: outcome.failed,
                pluginCount: recommended.length,
            }),
        };
        // SPEC-605: emit autopilot event after successful installs (fire-and-forget)
        if (outcome.installed.length > 0 && !dryRun) {
            emitAutopilotEvent({
                name: 'plugin:installed',
                projectPath,
                projectId,
                payload: { pluginIds: outcome.installed },
            });
        }
        return {
            content: [{ type: 'text', text: formatResult(result, signals, outcome.failedDetails) }],
        };
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        return {
            content: [
                {
                    type: 'text',
                    text: `install_plugins failed: ${message}. Ensure projectPath exists and try again.`,
                },
            ],
            isError: true,
        };
    }
}
function buildMessage(p) {
    if (p.dryRun) {
        return `Dry-run (${p.mode} mode): ${String(p.pluginCount)} plugin(s) identified. No changes made.`;
    }
    const parts = [];
    if (p.marketplaceStatus.registered) {
        parts.push('Marketplace registered');
    }
    if (p.installed.length > 0) {
        parts.push(`${String(p.installed.length)} installed`);
    }
    if (p.skipped.length > 0) {
        parts.push(`${String(p.skipped.length)} skipped (already installed)`);
    }
    if (p.failed.length > 0) {
        parts.push(`${String(p.failed.length)} failed`);
    }
    return parts.length > 0 ? parts.join(', ') + '.' : `Nothing to do (${p.mode} mode).`;
}
const TROUBLESHOOTING_HINTS = [
    '**Troubleshooting:**',
    '- Verify Claude CLI is installed: `claude --version`',
    '- Check network connectivity for marketplace plugins',
    '- Try installing individually: `claude plugin install <name>`',
    '- Run with `dryRun: true` first to preview without installing',
].join('\n');
function formatResult(r, signals, failedDetails = []) {
    const lines = [
        r.message,
        '',
        `| Field | Value |`,
        `|-------|-------|`,
        `| Mode | ${r.mode} |`,
        `| Dry run | ${String(r.dryRun)} |`,
        `| Marketplace | ${r.marketplaceAdded ? 'registered' : 'already registered / skipped'} |`,
        `| Installed | ${r.installed.length > 0 ? r.installed.join(', ') : '—'} |`,
        `| Skipped | ${r.skipped.length > 0 ? r.skipped.join(', ') : '—'} |`,
        `| Failed | ${r.failed.length > 0 ? r.failed.join(', ') : '—'} |`,
        `| Stack signals | ${signals.length > 0 ? signals.map((s) => s.name).join(', ') : '—'} |`,
    ];
    if (r.installed.length > 0 && !r.dryRun) {
        lines.push('', `**Auto-activated:** ${r.installed.join(', ')} — plugin configuration injected automatically.`);
    }
    if (failedDetails.length > 0) {
        lines.push('', '**Install Failures:**');
        for (const detail of failedDetails) {
            lines.push(`- \`${detail.pluginId}\` [${detail.errorType}]: ${detail.message}`);
            lines.push(`  → ${detail.recovery}`);
        }
        lines.push('', TROUBLESHOOTING_HINTS);
    }
    else if (r.failed.length > 0) {
        lines.push('', TROUBLESHOOTING_HINTS);
    }
    return lines.join('\n');
}
//# sourceMappingURL=install-plugins.js.map