import { spawnSync, execSync } from 'node:child_process';
import { inspect } from 'node:util';

// src/features/commit/infrastructure/git.ts
function runGitCommand(rootDir, command) {
  return execSync(command, {
    cwd: rootDir,
    encoding: "utf8",
    maxBuffer: 1024 * 1024 * 20,
    stdio: ["ignore", "pipe", "pipe"]
  }).trim();
}
function shellQuote(value) {
  return `'${value.replace(/'/g, `'\\''`)}'`;
}
function stringifyUnknown(value) {
  if (value === void 0 || value === null) {
    return "";
  }
  if (typeof value === "string") {
    return value;
  }
  if (Buffer.isBuffer(value)) {
    return value.toString("utf8");
  }
  if (value instanceof Error) {
    return value.stack || value.message;
  }
  return inspect(value, { depth: 6, breakLength: 120 });
}
function getErrorSummary(error) {
  if (error instanceof Error) {
    return `${error.name}: ${error.message}`;
  }
  return stringifyUnknown(error) || "Unknown error";
}

// src/features/commit/infrastructure/git.ts
function isRuntimeDirectoryIgnored(rootDir) {
  const result = spawnSync("git", ["check-ignore", "--quiet", "--no-index", ".ju-hong-e"], {
    cwd: rootDir,
    encoding: "utf8",
    maxBuffer: 1024 * 1024,
    stdio: ["ignore", "pipe", "pipe"]
  });
  return !result.error && result.status === 0;
}
function getStageWorkspaceArgs(rootDir) {
  const runtimeExcludeArgs = isRuntimeDirectoryIgnored(rootDir) ? [] : [":(exclude).ju-hong-e", ":(exclude).ju-hong-e/**"];
  return ["add", "-A", "--", ".", ...runtimeExcludeArgs];
}
function runGitCommandArgs(rootDir, args) {
  const preview = `git ${args.map(shellQuote).join(" ")}`;
  const result = spawnSync("git", args, {
    cwd: rootDir,
    encoding: "utf8",
    maxBuffer: 1024 * 1024 * 20,
    stdio: ["ignore", "pipe", "pipe"]
  });
  const stdout = result.stdout?.trim() || "";
  const stderr = result.stderr?.trim() || "";
  if (result.error || result.status !== 0) {
    throw new Error(`${preview} \uC2E4\uD589 \uC2E4\uD328: ${stderr || stdout || getErrorSummary(result.error || result.status)}`);
  }
  return {
    preview,
    stderr,
    stdout
  };
}
function stageWorkspaceChanges(rootDir) {
  const result = runGitCommandArgs(rootDir, getStageWorkspaceArgs(rootDir));
  return result.preview;
}
function commitWorkspaceChanges(rootDir, message) {
  const result = runGitCommandArgs(rootDir, ["commit", "-m", message]);
  return result.preview;
}
function getHeadHash(rootDir) {
  try {
    return runGitCommand(rootDir, "git rev-parse HEAD");
  } catch {
    return "";
  }
}
function getShortHeadHash(rootDir) {
  try {
    return runGitCommand(rootDir, "git rev-parse --short HEAD");
  } catch {
    return "";
  }
}
function getLatestCommitLog(rootDir) {
  try {
    return runGitCommand(
      rootDir,
      "git log -1 --stat --decorate=short --date=iso --format=%h%x20%d%x20%s%nAuthor:%x20%an%nDate:%x20%ad"
    );
  } catch {
    return "";
  }
}
function executeCommitWithMessage(options) {
  const commands = [];
  const headBefore = getHeadHash(options.rootDir);
  const addPreview = `git ${getStageWorkspaceArgs(options.rootDir).map(shellQuote).join(" ")}`;
  const commitPreview = options.draft.message ? `git commit -m ${shellQuote(options.draft.message)}` : "";
  const logPreview = "git log -1 --stat --decorate=short --date=iso --format=%h%x20%d%x20%s%nAuthor:%x20%an%nDate:%x20%ad";
  if (options.draft.message) {
    commands.push(addPreview, commitPreview, logPreview);
  }
  if (options.parsedArgs.testMode) {
    return {
      commands,
      errorMessage: "",
      gitLog: getLatestCommitLog(options.rootDir),
      headAfter: headBefore,
      headBefore,
      state: "skipped"
    };
  }
  if (options.draft.state !== "generated" || !options.draft.message) {
    const gitLog = getLatestCommitLog(options.rootDir);
    return {
      commands,
      errorMessage: options.draft.state === "failed" ? "AI \uC751\uB2F5\uC5D0\uC11C \uCEE4\uBC0B \uBA54\uC2DC\uC9C0\uB97C \uCD94\uCD9C\uD558\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4." : "",
      gitLog,
      headAfter: headBefore,
      headBefore,
      state: options.draft.state === "no-change" ? "no-change" : "failure"
    };
  }
  try {
    stageWorkspaceChanges(options.rootDir);
    commitWorkspaceChanges(options.rootDir, options.draft.message);
    const headAfter = getHeadHash(options.rootDir);
    const gitLog = getLatestCommitLog(options.rootDir);
    return {
      commands,
      errorMessage: "",
      gitLog,
      headAfter,
      headBefore,
      state: headBefore !== headAfter ? "success" : "no-change"
    };
  } catch (error) {
    return {
      commands,
      errorMessage: getErrorSummary(error),
      gitLog: getLatestCommitLog(options.rootDir),
      headAfter: getHeadHash(options.rootDir),
      headBefore,
      state: "failure"
    };
  }
}

export { executeCommitWithMessage, getHeadHash, getLatestCommitLog, getShortHeadHash, getStageWorkspaceArgs };
