import { spawnSync } from "node:child_process";
import { TASK_STATE_GIT_BRANCH } from "./constants.js";
const GIT_SPAWN_MAX_BUFFER_BYTES = 64 * 1024 * 1024;
export function runGit(cwd, argv) {
    const r = spawnSync("git", ["-C", cwd, ...argv], {
        encoding: "utf8",
        maxBuffer: GIT_SPAWN_MAX_BUFFER_BYTES
    });
    return {
        ok: r.status === 0,
        stdout: (r.stdout ?? "").trimEnd(),
        stderr: (r.stderr ?? "").trimEnd(),
        status: r.status
    };
}
export function isGitRepository(cwd) {
    const r = runGit(cwd, ["rev-parse", "--is-inside-work-tree"]);
    return r.ok && r.stdout.trim() === "true";
}
/** Resolve a local or remote-tracking ref for the canonical task-state branch. */
export function resolveTaskStateGitRef(cwd, branch = TASK_STATE_GIT_BRANCH) {
    const tried = [];
    const candidates = [
        `refs/remotes/origin/${branch}`,
        `origin/${branch}`,
        `refs/heads/${branch}`,
        branch
    ];
    for (const candidate of candidates) {
        tried.push(candidate);
        const r = runGit(cwd, ["rev-parse", "--verify", candidate]);
        if (r.ok && r.stdout.trim()) {
            return { ref: candidate, tipSha: r.stdout.trim() };
        }
    }
    return { missing: true, tried };
}
export function remoteBranchHeadSha(cwd, branch, remote = "origin") {
    const r = runGit(cwd, ["ls-remote", "--heads", remote, branch]);
    if (!r.ok || !r.stdout.trim()) {
        return null;
    }
    const line = r.stdout.split("\n").find((row) => row.trim().length > 0);
    if (!line) {
        return null;
    }
    const sha = line.split(/\s+/)[0]?.trim();
    return sha && sha.length > 0 ? sha : null;
}
export function gitFetchTaskStateBranch(cwd, branch = TASK_STATE_GIT_BRANCH) {
    return runGit(cwd, ["fetch", "origin", `${branch}:refs/remotes/origin/${branch}`]);
}
export function gitShowText(cwd, ref, filePath) {
    const r = runGit(cwd, ["show", `${ref}:${filePath}`]);
    if (!r.stdout) {
        return null;
    }
    return r.stdout;
}
export function gitLsTreeNames(cwd, ref, treePath) {
    const r = runGit(cwd, ["ls-tree", "-r", "--name-only", ref, treePath]);
    if (!r.ok || !r.stdout) {
        return [];
    }
    return r.stdout
        .split("\n")
        .map((line) => line.trim())
        .filter((line) => line.length > 0);
}
export function removeGitWorktree(repoCwd, worktreePath) {
    return runGit(repoCwd, ["worktree", "remove", "--force", worktreePath]);
}
