import { loadNative } from '../../infrastructure/native.js';
/**
 * BFS-based shortest path on a CodeGraph.
 *
 * Tries the native Rust implementation first, falls back to JS.
 *
 * @returns Path from fromId to toId (inclusive), or null if unreachable
 */
export function shortestPath(graph, fromId, toId) {
    const from = String(fromId);
    const to = String(toId);
    if (!graph.hasNode(from) || !graph.hasNode(to))
        return null;
    if (from === to)
        return [from];
    const native = loadNative();
    if (native?.shortestPath) {
        let edges = graph.toEdgeArray();
        if (!graph.directed) {
            // Undirected: toEdgeArray() deduplicates to one canonical direction;
            // mirror each edge so the Rust BFS can traverse in both directions.
            edges = [...edges, ...edges.map((e) => ({ source: e.target, target: e.source }))];
        }
        const result = native.shortestPath(edges, from, to);
        return result.length > 0 ? result : null;
    }
    return shortestPathJS(graph, from, to);
}
/** Pure JS fallback for shortest path. */
function shortestPathJS(graph, from, to) {
    const parent = new Map();
    parent.set(from, null);
    const queue = [from];
    let head = 0;
    while (head < queue.length) {
        const current = queue[head++];
        for (const neighbor of graph.successors(current)) {
            if (parent.has(neighbor))
                continue;
            parent.set(neighbor, current);
            if (neighbor === to) {
                const path = [];
                let node = to;
                while (node !== null) {
                    path.push(node);
                    node = parent.get(node) ?? null;
                }
                return path.reverse();
            }
            queue.push(neighbor);
        }
    }
    return null;
}
//# sourceMappingURL=shortest-path.js.map