import { toNormalizedSymbolKind } from '../types.js';
import { compareCodeUnits } from '../../utils.js';
import { normalizeRelativePath } from './resolve.js';
function sideMatches(event, side, query, expectedBodyHash, expectedKind) {
    const name = side === 'previous' ? event.previousName : event.currentName;
    const relativePath = side === 'previous' ? event.previousPath : event.currentPath;
    const kind = side === 'previous' ? event.previousKind : event.currentKind;
    const containerName = side === 'previous' ? event.previousContainerName : event.currentContainerName;
    const bodyHash = side === 'previous' ? event.previousBodyHash : event.currentBodyHash;
    if (name !== query.name || bodyHash !== expectedBodyHash)
        return false;
    if (!relativePath || normalizeRelativePath(relativePath) !== normalizeRelativePath(query.relativePath))
        return false;
    if (expectedKind && kind !== expectedKind)
        return false;
    if (query.containerName !== undefined && containerName !== query.containerName)
        return false;
    return true;
}
/**
 * Resolve an old stable symbol key to the current entity on the same lineage.
 *
 * The expected frozen body hash is required evidence. A name/path coincidence
 * alone is not enough to claim succession, and multiple surviving lineages are
 * returned as ambiguity rather than picked by iteration order.
 */
export function resolveEntitySuccessor(query, expectedBodyHash, context) {
    const expectedKind = query.kind ? toNormalizedSymbolKind(query.kind, query.containerName) : undefined;
    const lineageIds = new Set();
    for (const event of context.entityIndex.events) {
        if (sideMatches(event, 'previous', query, expectedBodyHash, expectedKind) ||
            sideMatches(event, 'current', query, expectedBodyHash, expectedKind)) {
            lineageIds.add(event.lineageId);
        }
    }
    const candidates = [];
    for (const lineageId of lineageIds) {
        const current = context.live.byLineageId.get(lineageId)?.ref;
        if (!current?.nodeId || current.provisional || current.indeterminate)
            continue;
        candidates.push(current);
    }
    candidates.sort((a, b) => compareCodeUnits(a.relativePath, b.relativePath) ||
        a.startLine - b.startLine ||
        compareCodeUnits(a.qualifiedName ?? a.name, b.qualifiedName ?? b.name));
    if (candidates.length === 1)
        return { status: 'resolved', successor: candidates[0] };
    if (candidates.length > 1)
        return { status: 'ambiguous', candidates };
    return { status: 'unavailable' };
}
//# sourceMappingURL=successor.js.map