// SPEC-597-EXEMPT: canonical mapping (npm-package↔framework, keyword catalogue)
// — must enumerate framework names by design; no detection logic to migrate.
// engine/reverse-engineer/orchestrator.ts — AC-7: Parallel analyzer orchestration
// AC-9: Spec enrichment from analysis results
// AC-10: Human-readable output summary
import { analyzeTestCoverage } from './test-analyzer.js';
import { buildDependencyGraph } from './dependency-graph.js';
import { detectApiRoutes } from './api-detector.js';
import { analyzeComplexity } from './complexity-analyzer.js';
import { analyzeConfig } from './config-analyzer.js';
const DEFAULT_OPTIONS = {
    enableTest: true,
    enableDeps: true,
    enableApi: true,
    enableComplexity: true,
    enableConfig: true,
};
export async function runDeepAnalysis(projectPath, options) {
    const opts = { ...DEFAULT_OPTIONS, ...options };
    const start = Date.now();
    // All analyzers are independent — run in parallel
    const [testCoverage, dependencyGraph, apiRoutes, complexityMetrics, configAnalysis] = await Promise.all([
        opts.enableTest
            ? Promise.resolve(analyzeTestCoverage(projectPath))
            : Promise.resolve(emptyTestCoverage()),
        opts.enableDeps
            ? Promise.resolve(buildDependencyGraph(projectPath))
            : Promise.resolve(emptyDependencyGraph()),
        opts.enableApi ? Promise.resolve(detectApiRoutes(projectPath)) : Promise.resolve([]),
        /* v8 ignore next 1 */
        opts.enableComplexity ? Promise.resolve(analyzeComplexity(projectPath)) : Promise.resolve([]),
        opts.enableConfig
            ? Promise.resolve(analyzeConfig(projectPath))
            : Promise.resolve(emptyConfigReport()),
    ]);
    return {
        testCoverage,
        dependencyGraph,
        apiRoutes,
        complexityMetrics,
        configAnalysis,
        analysisTimeMs: Date.now() - start,
    };
}
// --- AC-9: Spec enrichment helpers ---
function detectTags(result) {
    const tags = [];
    const tagMap = {
        jest: 'vitest/jest',
        vitest: 'vitest/jest',
        'next.config': 'nextjs',
        'vite.config': 'vite',
        tsconfig: 'typescript',
        docker: 'docker',
        Docker: 'docker',
    };
    for (const cfg of result.configAnalysis.configFiles) {
        for (const [key, tag] of Object.entries(tagMap)) {
            if (cfg.includes(key)) {
                tags.push(tag);
            }
        }
    }
    if (result.apiRoutes.length > 0) {
        const methods = new Set(result.apiRoutes.map((r) => r.method));
        if (methods.has('GET') && methods.has('POST')) {
            tags.push('rest-api');
        }
    }
    if (result.testCoverage.testedModules.length > 0) {
        tags.push('has-tests');
    }
    return [...new Set(tags)];
}
function detectTechDebt(result) {
    const items = [];
    if (result.testCoverage.untestedModules.length > 0) {
        items.push({
            file: 'multiple files',
            type: 'missing-tests',
            description: `${result.testCoverage.untestedModules.length} modules without tests`,
            severity: result.testCoverage.untestedModules.length > 10 ? 'high' : 'medium',
            effort: 'large',
            suggestion: 'Add tests for untested modules to improve coverage',
        });
    }
    if (result.dependencyGraph.cycles.length > 0) {
        items.push({
            file: 'dependency graph',
            type: 'anti-pattern',
            description: `${result.dependencyGraph.cycles.length} circular dependency cycle(s) detected`,
            severity: 'high',
            effort: 'medium',
            suggestion: 'Break circular dependencies by extracting shared interfaces',
        });
    }
    const hotspots = result.complexityMetrics
        .flatMap((m) => m.hotspots.map((h) => ({ ...h, file: m.file })))
        .sort((a, b) => b.complexity - a.complexity)
        .slice(0, 5);
    if (hotspots.length > 0) {
        items.push({
            /* v8 ignore next 2 */
            file: hotspots[0]?.file ?? 'unknown',
            type: 'code-smell',
            description: `${hotspots.length} high-complexity functions (top: ${hotspots[0]?.name} at ${hotspots[0]?.complexity})`,
            severity: 'medium',
            effort: 'medium',
            suggestion: 'Refactor complex functions into smaller, focused units',
        });
    }
    return items;
}
export function enrichSpecFromAnalysis(result) {
    const affectedFiles = result.dependencyGraph.nodes
        .slice()
        .sort((a, b) => b.fanIn - a.fanIn)
        .slice(0, 50)
        .map((n) => n.file);
    return { affectedFiles, tags: detectTags(result), techDebt: detectTechDebt(result) };
}
// --- AC-10: Output summary ---
function buildHealthLines(result) {
    const lines = ['', '## Health Indicators'];
    const { testCoverage } = result;
    const total = testCoverage.testedModules.length + testCoverage.untestedModules.length;
    const coveragePct = total > 0 ? Math.round((testCoverage.testedModules.length / total) * 100) : 0;
    lines.push(`- Test coverage: ${coveragePct}% (${testCoverage.testedModules.length}/${total} modules)`);
    lines.push(`- Circular dependencies: ${result.dependencyGraph.cycles.length}`);
    if (result.complexityMetrics.length > 0) {
        const avg = result.complexityMetrics.reduce((s, m) => s + m.avgComplexity, 0) /
            result.complexityMetrics.length;
        lines.push(`- Average complexity: ${avg.toFixed(1)}`);
    }
    lines.push(`- Config files: ${result.configAnalysis.configFiles.length}`);
    lines.push(`- Environment variables: ${result.configAnalysis.envVars.length}`);
    return lines;
}
export function generateAnalysisSummary(result) {
    const lines = ['## Architecture Overview'];
    const { nodes, hubs: hubList, orphans: orphanList } = result.dependencyGraph;
    lines.push(`- ${nodes.length} modules analyzed, ${hubList.length} hub(s), ${orphanList.length} orphan(s)`);
    if (result.apiRoutes.length > 0) {
        const resources = [...new Set(result.apiRoutes.map((r) => r.resource))];
        lines.push(`- ${result.apiRoutes.length} API routes across ${resources.length} resource(s): ${resources.slice(0, 5).join(', ')}`);
    }
    if (result.configAnalysis.infrastructure.length > 0) {
        lines.push(`- Infrastructure: ${result.configAnalysis.infrastructure.join(', ')}`);
    }
    lines.push(...buildHealthLines(result));
    // Top 5 risk areas
    lines.push('');
    lines.push('## Top 5 Risk Areas');
    const riskAreas = result.complexityMetrics
        .map((m) => ({
        file: m.file,
        complexity: m.avgComplexity,
        maxFnLen: m.maxFunctionLength,
        hasCoverage: result.testCoverage.testedModules.some((t) => m.file.includes(t) || t.includes(m.file)),
    }))
        .sort((a, b) => {
        const scoreA = a.complexity * (a.hasCoverage ? 1 : 2);
        const scoreB = b.complexity * (b.hasCoverage ? 1 : 2);
        return scoreB - scoreA;
    })
        .slice(0, 5);
    if (riskAreas.length === 0) {
        lines.push('- No significant risk areas detected');
    }
    else {
        for (const area of riskAreas) {
            const coverageLabel = area.hasCoverage ? 'tested' : 'UNTESTED';
            lines.push(`- **${area.file}**: complexity ${area.complexity.toFixed(1)}, max fn ${area.maxFnLen}L [${coverageLabel}]`);
        }
    }
    // Suggested decomposition
    lines.push('');
    lines.push('## Suggested Spec Decomposition');
    const hubs = result.dependencyGraph.hubs;
    if (hubs.length > 0) {
        lines.push(`- Hub modules (high fan-in) suggest natural spec boundaries: ${hubs.slice(0, 5).join(', ')}`);
    }
    if (result.apiRoutes.length > 0) {
        const resources = [...new Set(result.apiRoutes.map((r) => r.resource))];
        lines.push(`- API resources can be separate specs: ${resources.slice(0, 5).join(', ')}`);
    }
    if (result.dependencyGraph.orphans.length > 0) {
        lines.push(`- Orphan modules (no dependents) are safe to refactor independently: ${result.dependencyGraph.orphans.slice(0, 5).join(', ')}`);
    }
    lines.push('');
    lines.push(`*Analysis completed in ${result.analysisTimeMs}ms*`);
    return lines.join('\n');
}
// --- Empty defaults ---
function emptyTestCoverage() {
    return { testedModules: [], untestedModules: [], testToSourceRatio: 0 };
}
function emptyDependencyGraph() {
    return { nodes: [], cycles: [], hubs: [], orphans: [] };
}
function emptyConfigReport() {
    return { configFiles: [], envVars: [], featureFlags: [], infrastructure: [] };
}
//# sourceMappingURL=orchestrator.js.map