// engine/migration/strategy-advisor.ts — Migration strategy recommendation (SPEC-028a)
// Recommends big-bang, strangler-fig, or parallel-run based on project characteristics
// --- Strategy selection logic ---
function selectStrategy(input) {
    const { componentCount, hasActiveUsers, hasHighSla } = input;
    if (componentCount <= 10 && !hasActiveUsers) {
        return 'big-bang';
    }
    if (hasHighSla || input.hasCriticalData) {
        return 'parallel-run';
    }
    return 'strangler-fig';
}
function buildStranglerProxy(entryPoints) {
    const routingRules = entryPoints.map((ep) => ({
        module: ep,
        migrated: false,
        routeTo: 'old',
        condition: `Route to new when ${ep} migration is validated`,
    }));
    return {
        description: 'Proxy/API gateway routes traffic between old and new system based on migrated modules',
        routingRules,
        implementation: 'Implement a reverse proxy (nginx, Traefik, or custom middleware) that forwards requests based on a routing table. As each module is migrated and validated, update the routing table to direct traffic to the new system.',
    };
}
function detectNonIdempotentEndpoints(components) {
    return components
        .filter((c) => c.type === 'handler')
        .map((c) => c.name)
        .filter((name) => name.toLowerCase().includes('create') ||
        name.toLowerCase().includes('update') ||
        name.toLowerCase().includes('delete') ||
        name.toLowerCase().includes('send') ||
        name.toLowerCase().includes('payment'));
}
function buildParallelComparator(entryPoints, nonIdempotent) {
    const readEndpoints = entryPoints.filter((ep) => !nonIdempotent.some((ni) => ep.includes(ni)));
    return {
        description: 'Shadow mode comparator: runs both implementations and compares responses to validate parity before full cutover',
        endpoints: readEndpoints,
        tolerances: Object.fromEntries(readEndpoints.map((ep) => [ep, 0.01])),
        nonIdempotentEndpoints: nonIdempotent,
        excludedFromShadow: nonIdempotent,
    };
}
function getAlternatives(chosen) {
    const all = {
        'big-bang': 'Best for small codebases with no active users — high risk but fast',
        'strangler-fig': 'Gradual migration via proxy — safe for active systems',
        'parallel-run': 'Both systems run simultaneously — safest for critical systems with SLA',
    };
    return Object.entries(all)
        .filter(([s]) => s !== chosen)
        .map(([strategy, reason]) => ({ strategy, reason }));
}
function getRiskLevel(strategy, componentCount) {
    if (strategy === 'big-bang') {
        return componentCount > 5 ? 'high' : 'medium';
    }
    if (strategy === 'parallel-run') {
        return 'low';
    }
    return 'medium';
}
// --- Public API ---
export function recommendMigrationStrategy(params) {
    const strategy = selectStrategy(params);
    const nonIdempotent = detectNonIdempotentEndpoints(params.migratableComponents);
    let stranglerProxy;
    let parallelComparator;
    if (strategy === 'strangler-fig') {
        stranglerProxy = buildStranglerProxy(params.entryPoints);
    }
    else if (strategy === 'parallel-run') {
        parallelComparator = buildParallelComparator(params.entryPoints, nonIdempotent);
    }
    const reasonMap = {
        'big-bang': `Project has ${params.componentCount} components and no active users — full replacement is safest and fastest`,
        'strangler-fig': `Active user base detected — gradual migration via proxy minimizes risk and allows incremental validation`,
        'parallel-run': `High SLA or critical data requirements — both systems must run simultaneously to guarantee zero regression`,
    };
    return {
        recommended: strategy,
        reasoning: reasonMap[strategy],
        alternatives: getAlternatives(strategy),
        stranglerProxy,
        parallelComparator,
        riskLevel: getRiskLevel(strategy, params.componentCount),
    };
}
//# sourceMappingURL=strategy-advisor.js.map