/**
 * git-self-heal.ts — Automated git state recovery utilities.
 *
 * Four synchronous functions for recovering from broken git state
 * during auto-mode operations. Uses only `git reset --hard HEAD` —
 * never `git clean` (which would delete untracked .nerf/ dirs).
 *
 * Observability: Each function returns structured results describing
 * what actions were taken. `formatGitError` maps raw git errors to
 * user-friendly messages suggesting `/nerf doctor`.
 */
import { existsSync, unlinkSync } from "node:fs";
import { join } from "node:path";
import { MergeConflictError } from "./git-service.js";
import { nativeMergeAbort, nativeRebaseAbort, nativeResetHard } from "./native-git-bridge.js";
// Re-export for consumers
export { MergeConflictError };
/**
 * Detect and clean up leftover merge/rebase state, then hard-reset.
 *
 * Checks for: .git/MERGE_HEAD, .git/SQUASH_MSG, .git/rebase-apply.
 * Aborts in-progress merge or rebase if detected. Always finishes
 * with `git reset --hard HEAD`.
 *
 * @returns Structured result listing what was cleaned. Empty `cleaned`
 *          array means repo was already in a clean state.
 */
export function abortAndReset(cwd) {
    const gitDir = join(cwd, ".git");
    const cleaned = [];
    // Abort in-progress merge
    if (existsSync(join(gitDir, "MERGE_HEAD"))) {
        try {
            nativeMergeAbort(cwd);
            cleaned.push("aborted merge");
        }
        catch {
            // merge --abort can fail if state is really broken; continue to reset
            cleaned.push("merge abort attempted (may have failed)");
        }
    }
    // Remove leftover SQUASH_MSG (squash-merge leaves this without MERGE_HEAD)
    const squashMsgPath = join(gitDir, "SQUASH_MSG");
    if (existsSync(squashMsgPath)) {
        try {
            unlinkSync(squashMsgPath);
            cleaned.push("removed SQUASH_MSG");
        }
        catch {
            // Not critical
        }
    }
    // Abort in-progress rebase
    if (existsSync(join(gitDir, "rebase-apply")) || existsSync(join(gitDir, "rebase-merge"))) {
        try {
            nativeRebaseAbort(cwd);
            cleaned.push("aborted rebase");
        }
        catch {
            cleaned.push("rebase abort attempted (may have failed)");
        }
    }
    // Always hard-reset to HEAD
    try {
        nativeResetHard(cwd);
        if (cleaned.length > 0) {
            cleaned.push("reset to HEAD");
        }
    }
    catch {
        cleaned.push("reset to HEAD failed");
    }
    return { cleaned };
}
/** Known git error patterns mapped to user-friendly messages. */
const ERROR_PATTERNS = [
    {
        pattern: /conflict|CONFLICT|merge conflict/i,
        message: "A merge conflict occurred. Code changes on different branches touched the same files. Run `/nerf doctor` to diagnose.",
    },
    {
        pattern: /cannot checkout|did not match any|pathspec .* did not match/i,
        message: "Git could not switch branches — the target branch may not exist or the working tree is dirty. Run `/nerf doctor` to diagnose.",
    },
    {
        pattern: /HEAD detached|detached HEAD/i,
        message: "Git is in a detached HEAD state — not on any branch. Run `/nerf doctor` to diagnose and reattach.",
    },
    {
        pattern: /\.lock|Unable to create .* lock|lock file/i,
        message: "A git lock file is blocking operations. Another git process may be running, or a previous one crashed. Run `/nerf doctor` to diagnose.",
    },
    {
        pattern: /fatal: not a git repository/i,
        message: "This directory is not a git repository. Run `/nerf doctor` to check your project setup.",
    },
];
/**
 * Translate raw git error strings into user-friendly messages.
 *
 * Pattern-matches against common git error strings and returns
 * a non-technical message suggesting `/nerf doctor`. Returns the
 * original message if no pattern matches.
 */
export function formatGitError(error) {
    const errorStr = error instanceof Error ? error.message : error;
    for (const { pattern, message } of ERROR_PATTERNS) {
        if (pattern.test(errorStr)) {
            return message;
        }
    }
    return `A git error occurred: ${errorStr.slice(0, 200)}. Run \`/nerf doctor\` for help.`;
}
