"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CircularDependencyDetector = void 0;
class CircularDependencyDetector {
    buildGraph(imports) {
        const graph = new Map();
        for (const { from, to } of imports) {
            if (!graph.has(from))
                graph.set(from, new Set());
            graph.get(from).add(to);
        }
        return graph;
    }
    detectCycles(graph) {
        const cycles = [];
        const visited = new Set();
        const inStack = new Set();
        const path = [];
        const dfs = (node) => {
            visited.add(node);
            inStack.add(node);
            path.push(node);
            const neighbors = graph.get(node);
            if (neighbors) {
                for (const neighbor of neighbors) {
                    if (!visited.has(neighbor)) {
                        dfs(neighbor);
                    }
                    else if (inStack.has(neighbor)) {
                        const cycleStart = path.indexOf(neighbor);
                        const cycle = path.slice(cycleStart);
                        cycles.push({
                            cycle,
                            length: cycle.length,
                            breakPoint: this.findBreakPoint(cycle, graph),
                            breakReason: 'Least coupled node in the cycle',
                        });
                    }
                }
            }
            path.pop();
            inStack.delete(node);
        };
        for (const node of graph.keys()) {
            if (!visited.has(node)) {
                dfs(node);
            }
        }
        return cycles;
    }
    findBreakPoint(cycle, graph) {
        if (cycle.length === 0)
            return '';
        let minCoupling = Infinity;
        let breakPoint = cycle[0];
        for (const node of cycle) {
            const outDegree = graph.get(node)?.size || 0;
            let inDegree = 0;
            for (const [, neighbors] of graph) {
                if (neighbors.has(node))
                    inDegree++;
            }
            const coupling = outDegree + inDegree;
            if (coupling < minCoupling) {
                minCoupling = coupling;
                breakPoint = node;
            }
        }
        return breakPoint;
    }
    generateGraphVisualization(graph) {
        let dot = 'digraph Dependencies {\n';
        dot += '  rankdir=LR;\n';
        dot += '  node [shape=box, style=rounded];\n';
        for (const [from, neighbors] of graph) {
            for (const to of neighbors) {
                dot += `  "${from}" -> "${to}";\n`;
            }
        }
        dot += '}\n';
        return dot;
    }
    getStats(cycles) {
        if (cycles.length === 0)
            return { totalCycles: 0, maxLength: 0, avgLength: 0 };
        const lengths = cycles.map((c) => c.length);
        return {
            totalCycles: cycles.length,
            maxLength: Math.max(...lengths),
            avgLength: Math.round(lengths.reduce((a, b) => a + b, 0) / cycles.length),
        };
    }
}
exports.CircularDependencyDetector = CircularDependencyDetector;
//# sourceMappingURL=circular-dependency-detector.js.map