// tools/plan-mode-handler.ts — Plan Mode tool handlers (SPEC-473)
import { join } from 'node:path';
import { specStore, readJson, writeJson, projectDataDir, hashProjectPath, } from '../storage/index.js';
import { buildPlanFromSpec } from '../engine/plan-mode/plan-builder.js';
import { trackCost } from '../engine/cost-tracking/operation-tracker.js';
// ---------------------------------------------------------------------------
// Storage helpers
// ---------------------------------------------------------------------------
function planFilePath(projectId, planId) {
    return join(projectDataDir(projectId), 'plans', `${planId}.json`);
}
async function savePlan(projectId, plan) {
    await writeJson(planFilePath(projectId, plan.planId), plan);
}
async function loadPlan(projectId, planId) {
    const filePath = planFilePath(projectId, planId);
    const data = await readJson(filePath, null);
    return data;
}
// ---------------------------------------------------------------------------
// Formatters
// ---------------------------------------------------------------------------
function formatPlanPreview(plan) {
    const lines = [];
    lines.push(`# Plan Preview — ${plan.specId}`);
    lines.push('');
    lines.push(`**Plan ID**: \`${plan.planId}\``);
    lines.push(`**Created**: ${plan.createdAt}`);
    lines.push(`**Overall Risk**: ${plan.summary.overallRisk.toUpperCase()}`);
    lines.push('');
    lines.push('## Summary');
    lines.push('');
    lines.push(`| Metric | Value |`);
    lines.push(`|--------|-------|`);
    lines.push(`| Total files | ${plan.summary.totalFiles} |`);
    lines.push(`| Files to create | ${plan.summary.filesToCreate} |`);
    lines.push(`| Files to modify | ${plan.summary.filesToModify} |`);
    lines.push(`| Files to delete | ${plan.summary.filesToDelete} |`);
    lines.push(`| Est. lines added | +${plan.summary.estimatedLinesAdded} |`);
    lines.push(`| Est. lines removed | -${plan.summary.estimatedLinesRemoved} |`);
    lines.push('');
    if (plan.files.length > 0) {
        lines.push('## File Changes');
        lines.push('');
        lines.push('| File | Action | +Lines | -Lines | Risk |');
        lines.push('|------|--------|--------|--------|------|');
        for (const f of plan.files) {
            lines.push(`| \`${f.path}\` | ${f.action} | +${f.estimatedLinesAdded} | -${f.estimatedLinesRemoved} | ${f.riskLevel} |`);
        }
        lines.push('');
    }
    if (plan.warnings.length > 0) {
        lines.push('## Warnings');
        lines.push('');
        for (const w of plan.warnings) {
            lines.push(`- ${w}`);
        }
        lines.push('');
    }
    lines.push(`To approve and implement: call \`implement_plan\` with planId \`${plan.planId}\`.`);
    return lines.join('\n');
}
// ---------------------------------------------------------------------------
// Handlers
// ---------------------------------------------------------------------------
/** Generate a diff preview plan for a spec without implementing anything. */
export async function handlePlanMode(args) {
    return trackCost(args.projectPath, 'plan_mode', async () => {
        const projectId = hashProjectPath(args.projectPath);
        const spec = await specStore.getSpec(projectId, args.specId);
        if (!spec) {
            return {
                content: [
                    {
                        type: 'text',
                        text: `Spec "${args.specId}" not found in project at ${args.projectPath}. Run list_specs to see available specs.`,
                    },
                ],
            };
        }
        const plan = await buildPlanFromSpec(spec);
        await savePlan(projectId, plan);
        return {
            content: [
                {
                    type: 'text',
                    text: formatPlanPreview(plan),
                },
            ],
        };
    }); // end trackCost
}
/** Mark a plan as approved. The plan is persisted with an approved flag. */
export async function handleImplementPlan(args) {
    return trackCost(args.projectPath, 'implement_plan', async () => {
        const projectId = hashProjectPath(args.projectPath);
        const plan = await loadPlan(projectId, args.planId);
        if (!plan) {
            return {
                content: [
                    {
                        type: 'text',
                        text: `Plan "${args.planId}" not found. Generate a plan first with plan_mode.`,
                    },
                ],
            };
        }
        // Persist plan with approval marker
        const approvedPlan = { ...plan, approvedAt: new Date().toISOString() };
        await writeJson(planFilePath(projectId, args.planId), approvedPlan);
        const lines = [
            `# Plan Approved — ${plan.specId}`,
            '',
            `**Plan ID**: \`${plan.planId}\``,
            `**Spec**: ${plan.specId}`,
            `**Files to touch**: ${plan.summary.totalFiles}`,
            `**Est. lines**: +${plan.summary.estimatedLinesAdded} / -${plan.summary.estimatedLinesRemoved}`,
            '',
            'The plan has been approved. Proceed with implementation using update_status and your preferred implementation workflow.',
        ];
        return {
            content: [
                {
                    type: 'text',
                    text: lines.join('\n'),
                },
            ],
        };
    }); // end trackCost
}
//# sourceMappingURL=plan-mode-handler.js.map