import { SUPERBLOCKS_LIVE_GIT_BRANCH } from "@superblocksteam/shared";
import { getErrorMeta, getLogger } from "../util/logger.js";
import { GitAuthError, GitPermissionError } from "./errors.js";
import { classifyGitError } from "./index.js";
export async function ensureLiveBranchCheckedOut(gitService) {
    const logger = getLogger();
    const currentBranch = await gitService
        .raw(["branch", "--show-current"])
        .then((branch) => branch.trim())
        .catch(() => "");
    if (currentBranch === SUPERBLOCKS_LIVE_GIT_BRANCH) {
        // Only this SABS process writes to superblocks/live for a given app,
        // so a local checkout already on the correct branch is up to date.
        return;
    }
    logger.warn("[git] live branch mismatch detected", {
        gitCategory: "branch",
        gitOperation: "checkout-live-branch",
        gitOutcome: "fallback",
        currentBranch: currentBranch || "(detached)",
        targetBranch: SUPERBLOCKS_LIVE_GIT_BRANCH,
    });
    try {
        await gitService.fetch("origin", SUPERBLOCKS_LIVE_GIT_BRANCH);
    }
    catch (fetchErr) {
        const classified = classifyGitError(fetchErr);
        if (classified instanceof GitAuthError ||
            classified instanceof GitPermissionError) {
            throw classified;
        }
        logger.warn("[git] live branch fetch failed, proceeding with local ref", {
            gitCategory: "branch",
            gitOperation: "checkout-live-branch",
            gitOutcome: "fetch_failed",
            branch: SUPERBLOCKS_LIVE_GIT_BRANCH,
            ...getErrorMeta(fetchErr),
        });
    }
    try {
        await gitService.revparse(`origin/${SUPERBLOCKS_LIVE_GIT_BRANCH}`);
        await gitService.checkoutOrCreate(SUPERBLOCKS_LIVE_GIT_BRANCH, `origin/${SUPERBLOCKS_LIVE_GIT_BRANCH}`);
        logger.info("[git] live branch switched from remote", {
            gitCategory: "branch",
            gitOperation: "checkout-live-branch",
            gitOutcome: "succeeded",
            targetBranch: SUPERBLOCKS_LIVE_GIT_BRANCH,
            startPoint: `origin/${SUPERBLOCKS_LIVE_GIT_BRANCH}`,
        });
    }
    catch {
        await gitService.checkoutOrCreate(SUPERBLOCKS_LIVE_GIT_BRANCH);
        logger.info("[git] live branch created locally", {
            gitCategory: "branch",
            gitOperation: "checkout-live-branch",
            gitOutcome: "fallback",
            targetBranch: SUPERBLOCKS_LIVE_GIT_BRANCH,
        });
    }
}
export async function doesRemoteLiveBranchExist(gitService) {
    try {
        const remoteRefs = await gitService.raw([
            "ls-remote",
            "--heads",
            "origin",
            `refs/heads/${SUPERBLOCKS_LIVE_GIT_BRANCH}`,
        ]);
        return remoteRefs.includes(`refs/heads/${SUPERBLOCKS_LIVE_GIT_BRANCH}`);
    }
    catch (error) {
        getLogger().warn("[git] live branch existence check failed", {
            gitCategory: "branch",
            gitOperation: "check-live-branch-exists",
            gitOutcome: "failed",
            branch: SUPERBLOCKS_LIVE_GIT_BRANCH,
            message: error instanceof Error ? error.message : String(error),
        });
        return null;
    }
}
export async function pushLiveBranchWithAutoRecreate(gitService) {
    const remoteExists = await doesRemoteLiveBranchExist(gitService);
    if (remoteExists === false) {
        getLogger().warn("[git] live branch missing on remote", {
            gitCategory: "branch",
            gitOperation: "check-live-branch-exists",
            gitOutcome: "failed",
            branch: SUPERBLOCKS_LIVE_GIT_BRANCH,
        });
    }
    try {
        getLogger().info("[git] live branch push started", {
            gitCategory: "commit",
            gitOperation: "push-live-branch",
            gitOutcome: "started",
            branch: SUPERBLOCKS_LIVE_GIT_BRANCH,
        });
        await gitService.push("origin", SUPERBLOCKS_LIVE_GIT_BRANCH);
        getLogger().info("[git] live branch push succeeded", {
            gitCategory: "commit",
            gitOperation: "push-live-branch",
            gitOutcome: "succeeded",
            branch: SUPERBLOCKS_LIVE_GIT_BRANCH,
            recreated: false,
        });
    }
    catch (pushError) {
        // Classify the error so permission/auth failures surface immediately.
        const classified = classifyGitError(pushError);
        if (classified instanceof GitPermissionError ||
            classified instanceof GitAuthError) {
            throw classified;
        }
        // Fallback path: explicitly push HEAD to recreate missing remote live branch.
        getLogger().warn("[git] live branch push fallback starting", {
            gitCategory: "branch",
            gitOperation: "push-live-branch",
            gitOutcome: "fallback",
            branch: SUPERBLOCKS_LIVE_GIT_BRANCH,
            fallback: "explicit-head-push",
            error: getErrorMeta(pushError).error.message,
        });
        await ensureLiveBranchCheckedOut(gitService);
        await gitService.raw([
            "push",
            "origin",
            `HEAD:${SUPERBLOCKS_LIVE_GIT_BRANCH}`,
        ]);
        getLogger().info("[git] live branch recreated on remote", {
            gitCategory: "branch",
            gitOperation: "push-live-branch",
            gitOutcome: "succeeded",
            branch: SUPERBLOCKS_LIVE_GIT_BRANCH,
            recreated: true,
        });
    }
}
export async function rollbackLastCommit({ gitService, expectedSha, }) {
    const headSha = (await gitService.revparse("HEAD")).trim();
    if (headSha !== expectedSha) {
        getLogger().warn("[git] rollback skipped due to head mismatch", {
            gitCategory: "commit",
            gitOperation: "rollback",
            gitOutcome: "skipped",
            headSha,
            expectedSha,
        });
        return { rolledBack: false };
    }
    getLogger().info("[git] rollback started", {
        gitCategory: "commit",
        gitOperation: "rollback",
        gitOutcome: "started",
        expectedSha,
    });
    await gitService.raw(["reset", "--mixed", "HEAD~1"]);
    getLogger().info("[git] rollback succeeded", {
        gitCategory: "commit",
        gitOperation: "rollback",
        gitOutcome: "succeeded",
        expectedSha,
    });
    return { rolledBack: true };
}
//# sourceMappingURL=live-branch.js.map