"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.discoverGitRemoteNames = discoverGitRemoteNames;
exports.discoverGitRemoteUrl = discoverGitRemoteUrl;
exports.discoverGitRemoteDefaultBranch = discoverGitRemoteDefaultBranch;
const native_git_cli_1 = require("./native-git-cli");
async function discoverGitRemoteNames(repositoryRoot) {
    try {
        const remotes = await (0, native_git_cli_1.readNativeGit)(repositoryRoot, ["remote"]);
        return remotes
            .split(/\r?\n/u)
            .map((remoteName) => remoteName.trim())
            .filter((remoteName) => remoteName.length > 0)
            .sort((left, right) => left.localeCompare(right));
    }
    catch {
        return [];
    }
}
async function discoverGitRemoteUrl(repositoryRoot, remoteName) {
    try {
        const remoteUrl = await (0, native_git_cli_1.readNativeGit)(repositoryRoot, [
            "remote",
            "get-url",
            remoteName,
        ]);
        return remoteUrl.trim() || null;
    }
    catch {
        return null;
    }
}
async function discoverGitRemoteDefaultBranch(repositoryRoot, remoteName) {
    try {
        const currentBranch = (await (0, native_git_cli_1.readNativeGit)(repositoryRoot, ["branch", "--show-current"])).trim();
        if (currentBranch) {
            const trackedBranch = await readTrackedRemoteBranch(repositoryRoot, currentBranch, remoteName);
            if (trackedBranch) {
                return trackedBranch;
            }
        }
        const remoteBranches = await listRemoteBranches(repositoryRoot, remoteName);
        if (remoteBranches.includes("main")) {
            return "main";
        }
        if (remoteBranches.includes("master")) {
            return "master";
        }
        if (currentBranch && remoteBranches.includes(currentBranch)) {
            return currentBranch;
        }
        return remoteBranches.length === 1 ? (remoteBranches[0] ?? null) : null;
    }
    catch {
        return null;
    }
}
async function readTrackedRemoteBranch(repositoryRoot, branchName, remoteName) {
    const [remote, merge] = await Promise.all([
        readGitConfigValue(repositoryRoot, `branch.${branchName}.remote`),
        readGitConfigValue(repositoryRoot, `branch.${branchName}.merge`),
    ]);
    if (remote !== remoteName || typeof merge !== "string") {
        return null;
    }
    const trackedBranch = merge.startsWith("refs/heads/")
        ? merge.slice("refs/heads/".length)
        : null;
    if (!trackedBranch) {
        return null;
    }
    return (await refExists(repositoryRoot, `refs/remotes/${remoteName}/${trackedBranch}`))
        ? trackedBranch
        : null;
}
async function refExists(repositoryRoot, ref) {
    try {
        await (0, native_git_cli_1.readNativeGit)(repositoryRoot, ["rev-parse", "--verify", ref]);
        return true;
    }
    catch {
        return false;
    }
}
async function readGitConfigValue(repositoryRoot, key) {
    try {
        const value = await (0, native_git_cli_1.readNativeGit)(repositoryRoot, ["config", "--get", key]);
        return value.trim() || null;
    }
    catch (error) {
        if ((0, native_git_cli_1.isNativeGitExitCode)(error, 1)) {
            return null;
        }
        throw error;
    }
}
async function listRemoteBranches(repositoryRoot, remoteName) {
    const output = await (0, native_git_cli_1.readNativeGit)(repositoryRoot, [
        "for-each-ref",
        "--format=%(refname:short)",
        `refs/remotes/${remoteName}`,
    ]);
    return output
        .split(/\r?\n/u)
        .map((line) => line.trim())
        .filter((line) => line.length > 0 && line !== `${remoteName}/HEAD`)
        .map((line) => line.startsWith(`${remoteName}/`)
        ? line.slice(`${remoteName}/`.length)
        : line)
        .sort((left, right) => left.localeCompare(right));
}
