// tools/generate-execution-plan.ts — Execution plan tool handler + orchestrator
// SRP: this file owns only tool I/O and phase orchestration.
// Phase logic lives in src/engine/execution-plan/phases.ts
// Mobile distribution lives in src/engine/execution-plan/mobile-distribution.ts
// Utilities live in src/engine/execution-plan/plan-utils.ts
import { writeFile } from 'node:fs/promises';
import { dirname, join } from 'node:path';
import { specStore, knowledgeStore, patternStore } from '../storage/index.js';
import { t, ti } from '../i18n/index.js';
import { generatePlanMarkdown } from '../engine/dor-dod.js';
import { generateSetupPhase, generateDataLayerPhase, generateBusinessLogicPhase, generateUIPhase, generateTestingPhase, generateIntegrationPhase, } from '../engine/execution-plan/phases.js';
import { generateMobileDistributionPhase, isMobileDistributionSpec, } from '../engine/execution-plan/mobile-distribution.js';
import { isDesktopReleaseSpec, generateDesktopDistributionPhase, } from '../engine/execution-plan/desktop-distribution.js';
import { determineCriticalPath, findParallelizable, readSpecContent, } from '../engine/execution-plan/plan-utils.js';
export async function handleGenerateExecutionPlan(args) {
    const { specId, projectId } = args;
    const spec = await specStore.getSpec(projectId, specId);
    if (!spec) {
        return {
            content: [{ type: 'text', text: ti('spec.notFound', { id: specId }) }],
            isError: true,
        };
    }
    const knowledge = await knowledgeStore.getKnowledge(projectId);
    if (!knowledge) {
        return {
            content: [{ type: 'text', text: t('project.notFound') }],
            isError: true,
        };
    }
    await patternStore.listPatterns(projectId);
    const specContent = await readSpecContent(spec);
    const phases = generatePhases(spec, knowledge, specContent);
    const criticalPath = determineCriticalPath(phases);
    const parallelizable = findParallelizable(phases);
    const totalSteps = phases.reduce((sum, phase) => sum + phase.steps.length, 0);
    const totalMinutes = phases.reduce((sum, phase) => sum + phase.steps.reduce((s, step) => s + step.estimatedMinutes, 0), 0);
    const plan = { phases, totalSteps, criticalPath, parallelizable };
    let planPath;
    try {
        const planDir = dirname(spec.huPath);
        planPath = join(planDir, 'PLAN.md');
        const planContent = generatePlanMarkdown(plan, spec);
        await writeFile(planPath, planContent, 'utf-8');
        await specStore.updateSpec(projectId, specId, { planPath });
    }
    catch {
        planPath = undefined;
    }
    return {
        content: [
            {
                type: 'text',
                text: ti('tools.generate_execution_plan.success', {
                    phaseCount: String(phases.length),
                    stepCount: String(totalSteps),
                }),
            },
            {
                type: 'text',
                text: JSON.stringify({
                    ...plan,
                    planPath: planPath ?? null,
                    summary: {
                        phases: phases.length,
                        totalSteps,
                        estimatedMinutes: totalMinutes,
                        estimatedHours: Math.round((totalMinutes / 60) * 10) / 10,
                        criticalPathLength: criticalPath.length,
                        parallelizableGroups: parallelizable.length,
                    },
                }, null, 2),
            },
        ],
    };
}
// --- Phase dispatcher (OCP: add new phases here without modifying phase files) ---
function generatePhases(spec, knowledge, specContent) {
    const phases = [];
    let stepOrder = 1;
    const setupSteps = generateSetupPhase(spec, knowledge, stepOrder);
    if (setupSteps.length > 0) {
        phases.push({ name: 'Setup & Scaffolding', steps: setupSteps });
        stepOrder += setupSteps.length;
    }
    if (spec.target === 'backend' || spec.target === 'fullstack' || spec.target === 'database') {
        const dataSteps = generateDataLayerPhase(spec, knowledge, specContent, stepOrder);
        if (dataSteps.length > 0) {
            phases.push({ name: 'Data Layer', steps: dataSteps });
            stepOrder += dataSteps.length;
        }
    }
    if (spec.target !== 'frontend') {
        const logicSteps = generateBusinessLogicPhase(spec, knowledge, specContent, stepOrder);
        if (logicSteps.length > 0) {
            phases.push({ name: 'Business Logic & API', steps: logicSteps });
            stepOrder += logicSteps.length;
        }
    }
    if (spec.target === 'frontend' || spec.target === 'fullstack') {
        const uiSteps = generateUIPhase(spec, knowledge, specContent, stepOrder);
        if (uiSteps.length > 0) {
            phases.push({ name: 'UI Implementation', steps: uiSteps });
            stepOrder += uiSteps.length;
        }
    }
    const testSteps = generateTestingPhase(spec, knowledge, stepOrder);
    phases.push({ name: 'Testing & Verification', steps: testSteps });
    stepOrder += testSteps.length;
    // SPEC-013: Distribution phase for mobile release specs (iOS/Android/Flutter/RN/Expo)
    if (isMobileDistributionSpec(spec)) {
        const distSteps = generateMobileDistributionPhase(spec, stepOrder);
        if (distSteps.length > 0) {
            phases.push({ name: 'Distribution & Store Submission', steps: distSteps });
            stepOrder += distSteps.length;
        }
    }
    // SPEC-014b: Distribution phase for desktop release specs
    if (knowledge.projectCategory === 'desktop' && isDesktopReleaseSpec(spec)) {
        const desktopDistSteps = generateDesktopDistributionPhase(spec, stepOrder);
        if (desktopDistSteps.length > 0) {
            phases.push({ name: 'Distribution', steps: desktopDistSteps });
            stepOrder += desktopDistSteps.length;
        }
    }
    const integrationSteps = generateIntegrationPhase(spec, knowledge, stepOrder);
    phases.push({ name: 'Integration & Cleanup', steps: integrationSteps });
    return phases;
}
//# sourceMappingURL=generate-execution-plan.js.map