import { createLogger } from '../../shared/utils/index.js';
import { listCandidateRefs } from './branchBaseRefCache.js';
import { runGit } from './branchGitCommands.js';
const TAKT_COMMIT_PREFIX = 'takt:';
const log = createLogger('branchGitResolver');
export function resolveMergeBase(gitCwd, baseRef, branch) {
    return runGit(gitCwd, ['merge-base', baseRef, branch]);
}
function buildPriorityRefs(defaultBranch, branch) {
    const refs = [defaultBranch, `origin/${defaultBranch}`];
    const distinctRefs = [];
    for (const ref of refs) {
        if (!ref || ref === branch || ref.endsWith(`/${branch}`)) {
            continue;
        }
        if (!distinctRefs.includes(ref)) {
            distinctRefs.push(ref);
        }
    }
    return distinctRefs;
}
function getFirstParentDistance(gitCwd, baseCommit, branch) {
    const output = runGit(gitCwd, ['rev-list', '--count', '--first-parent', `${baseCommit}..${branch}`]);
    return Number.parseInt(output, 10);
}
function getFirstParentFirstSubject(gitCwd, baseCommit, branch) {
    const output = runGit(gitCwd, ['log', '--format=%s', '--reverse', '--first-parent', `${baseCommit}..${branch}`]);
    const firstLine = output.split('\n')[0];
    if (!firstLine) {
        return '';
    }
    return firstLine.trim();
}
function resolveBaseCandidate(gitCwd, baseRef, branch) {
    try {
        const baseCommit = resolveMergeBase(gitCwd, baseRef, branch);
        if (!baseCommit) {
            return null;
        }
        const distance = getFirstParentDistance(gitCwd, baseCommit, branch);
        if (!Number.isFinite(distance) || distance <= 0) {
            return null;
        }
        const firstSubject = getFirstParentFirstSubject(gitCwd, baseCommit, branch);
        return { baseRef, baseCommit, firstSubject, distance };
    }
    catch (error) {
        log.debug('Failed to resolve base candidate', { error: String(error), gitCwd, baseRef, branch });
        return null;
    }
}
function chooseBestBaseCandidate(candidates) {
    if (candidates.length === 0) {
        return null;
    }
    const sorted = [...candidates].sort((a, b) => {
        const aTakt = a.firstSubject.startsWith(TAKT_COMMIT_PREFIX);
        const bTakt = b.firstSubject.startsWith(TAKT_COMMIT_PREFIX);
        if (aTakt !== bTakt) {
            return aTakt ? -1 : 1;
        }
        if (a.distance !== b.distance) {
            return a.distance - b.distance;
        }
        const aRemote = a.baseRef.includes('/');
        const bRemote = b.baseRef.includes('/');
        if (aRemote !== bRemote) {
            return aRemote ? 1 : -1;
        }
        return a.baseRef.localeCompare(b.baseRef);
    });
    const best = sorted[0];
    return best ? best : null;
}
export function resolveBranchBaseCommitFromRefs(gitCwd, defaultBranch, branch, cache) {
    const priorityRefs = buildPriorityRefs(defaultBranch, branch);
    const priorityCandidates = [];
    for (const ref of priorityRefs) {
        const candidate = resolveBaseCandidate(gitCwd, ref, branch);
        if (candidate) {
            priorityCandidates.push(candidate);
        }
    }
    const priorityBest = chooseBestBaseCandidate(priorityCandidates);
    if (priorityBest) {
        return priorityBest.baseCommit;
    }
    const refs = listCandidateRefs(gitCwd, branch, cache).filter(ref => !priorityRefs.includes(ref));
    const candidates = [];
    for (const ref of refs) {
        const candidate = resolveBaseCandidate(gitCwd, ref, branch);
        if (candidate) {
            candidates.push(candidate);
        }
    }
    const best = chooseBestBaseCandidate(candidates);
    if (!best) {
        return null;
    }
    return best.baseCommit;
}
//# sourceMappingURL=branchBaseCandidateResolver.js.map