import { execSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import { inspect } from 'node:util';

// src/platform/core/report-helpers.ts

// src/platform/core/git-helpers.ts
function formatCodeBlock(content, language = "") {
  return `\`\`\`${language}
${content || "(\uC5C6\uC74C)"}
\`\`\``;
}
function formatWorkspaceSnapshot(snapshot) {
  if (!snapshot.available) {
    return snapshot.note;
  }
  return [
    `- Git Root: \`${snapshot.gitRoot}\``,
    `- Branch: \`${snapshot.branch || "(detached)"}\``,
    "",
    "### git status --short",
    formatCodeBlock(snapshot.statusLines.join("\n")),
    "",
    "### git diff --stat",
    formatCodeBlock(snapshot.diffStat),
    "",
    "### git diff --name-status",
    formatCodeBlock(snapshot.diffNameStatus),
    "",
    "### \uCD5C\uADFC \uCEE4\uBC0B",
    formatCodeBlock(snapshot.recentCommits.join("\n"))
  ].join("\n");
}
function formatWorkspaceDelta(delta) {
  return [
    "### \uC0C8\uB85C \uAC10\uC9C0\uB41C \uC0C1\uD0DC",
    formatCodeBlock(delta.afterOnly.join("\n")),
    "",
    "### \uC0AC\uB77C\uC9C4 \uC774\uC804 \uC0C1\uD0DC",
    formatCodeBlock(delta.beforeOnly.join("\n")),
    "",
    "### \uC601\uD5A5 \uD30C\uC77C",
    formatCodeBlock(delta.touchedFiles.join("\n"))
  ].join("\n");
}
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/platform/core/timestamp-helpers.ts
function padTimestampPart(value) {
  return String(value).padStart(2, "0");
}
function getTimestampParts(now = /* @__PURE__ */ new Date()) {
  return {
    year: now.getFullYear(),
    month: padTimestampPart(now.getMonth() + 1),
    day: padTimestampPart(now.getDate()),
    hour: padTimestampPart(now.getHours()),
    minute: padTimestampPart(now.getMinutes()),
    second: padTimestampPart(now.getSeconds())
  };
}
function getFileTimestamp(now = /* @__PURE__ */ new Date()) {
  const { year, month, day, hour, minute, second } = getTimestampParts(now);
  return `${year}-${month}-${day}_${hour}-${minute}-${second}`;
}
function getDashedFileTimestamp(now = /* @__PURE__ */ new Date()) {
  const { year, month, day, hour, minute, second } = getTimestampParts(now);
  return `${year}-${month}-${day}-${hour}-${minute}-${second}`;
}
function getHumanReadableNow(now = /* @__PURE__ */ new Date()) {
  const { year, month, day, hour, minute, second } = getTimestampParts(now);
  return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}

// src/platform/core/report-helpers.ts
function getAvailableFilePath(directory, baseName, extension) {
  const first = path.join(directory, `${baseName}${extension}`);
  if (!fs.existsSync(first)) {
    return first;
  }
  let next = first;
  let count = 1;
  while (fs.existsSync(next)) {
    next = path.join(directory, `${baseName}-${count}${extension}`);
    if (!fs.existsSync(next)) {
      break;
    }
    count += 1;
  }
  return next;
}
function appendHistoryIndex(paths, summary, relativeFilePath) {
  const line = `- ${getHumanReadableNow()} | ${summary} | file: \`${relativeFilePath}\`
`;
  fs.appendFileSync(paths.historyIndexPath, line, "utf8");
}
function renderSections(sections = []) {
  if (sections.length === 0) {
    return "";
  }
  return sections.map((section) => `
## ${section.heading}

${section.markdown}
`).join("\n");
}
function serializeError(error) {
  const serialized = {
    summary: getErrorSummary(error)
  };
  if (error instanceof Error) {
    serialized.name = error.name;
    serialized.message = error.message;
    serialized.stack = error.stack;
  } else {
    serialized.value = stringifyUnknown(error);
  }
  if (error && typeof error === "object") {
    const errorLike = error;
    ["code", "errno", "syscall", "path", "cmd", "status", "signal"].forEach((key) => {
      if (errorLike[key] !== void 0) {
        serialized[key] = errorLike[key];
      }
    });
    const stdout = stringifyUnknown(errorLike.stdout);
    if (stdout) {
      serialized.stdout = stdout;
    }
    const stderr = stringifyUnknown(errorLike.stderr);
    if (stderr) {
      serialized.stderr = stderr;
    }
  }
  return serialized;
}
function writeCodeReviewArtifact(paths, baseNameSuffix, content) {
  const filePath = getAvailableFilePath(paths.codeReviewDir, `${getDashedFileTimestamp()}-${baseNameSuffix}`, ".md");
  const normalizedContent = content?.trim() || "(\uC751\uB2F5 \uC5C6\uC74C)";
  fs.writeFileSync(filePath, `${normalizedContent}
`, "utf8");
  return filePath;
}
function writeCodeReviewReport(paths, reviewOutput) {
  return writeCodeReviewArtifact(paths, "code-review", reviewOutput);
}
function writeCodeReviewDiffFile(paths, diffOutput) {
  return writeCodeReviewArtifact(paths, "diff", diffOutput);
}
function openReportInBrowser(reportPath) {
  const resolvedPath = path.resolve(reportPath);
  const { platform } = process;
  const openWithChrome = () => {
    if (platform === "darwin") {
      execSync(`open -a "Google Chrome" "${resolvedPath}"`, { stdio: "ignore" });
      return true;
    }
    if (platform === "linux") {
      execSync(`google-chrome "${resolvedPath}"`, { stdio: "ignore" });
      return true;
    }
    return false;
  };
  const openWithDefaultBrowser = () => {
    if (platform === "darwin") {
      execSync(`open "${resolvedPath}"`, { stdio: "ignore" });
      return true;
    }
    if (platform === "linux") {
      execSync(`xdg-open "${resolvedPath}"`, { stdio: "ignore" });
      return true;
    }
    return false;
  };
  try {
    if (openWithChrome()) {
      console.log(`Google Chrome\uC5D0\uC11C \uB9AC\uBDF0 \uC774\uB825\uC744 \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4: ${resolvedPath}`);
      return;
    }
  } catch {
  }
  try {
    if (openWithDefaultBrowser()) {
      console.log(`\uAE30\uBCF8 \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB9AC\uBDF0 \uC774\uB825\uC744 \uC5F4\uC5C8\uC2B5\uB2C8\uB2E4: ${resolvedPath}`);
      return;
    }
  } catch (error) {
    console.error(`\uAE30\uBCF8 \uBE0C\uB77C\uC6B0\uC800\uB85C \uB9AC\uBDF0 \uC774\uB825\uC744 \uC5F4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${getErrorSummary(error)}`);
    return;
  }
  console.error(`\uC9C0\uC6D0\uD558\uC9C0 \uC54A\uB294 \uD50C\uB7AB\uD3FC\uC774\uB77C \uB9AC\uBDF0 \uC774\uB825\uC744 \uC790\uB3D9\uC73C\uB85C \uC5F4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4: ${platform}`);
}
function writeTurnHistory(paths, record) {
  const baseName = `${getFileTimestamp()}-${record.scope}`;
  const filePath = getAvailableFilePath(paths.turnsDir, baseName, ".md");
  const markdown = `# ${record.title}

- \uC2DC\uAC01: ${getHumanReadableNow()}
- scope: \`${record.scope}\`
- service: \`${record.service}\`
- skipped: \`${record.skipped}\`

## \uC0AC\uC6A9\uC790 \uC785\uB825

${formatCodeBlock(record.input)}

## AI \uC751\uB2F5

${record.output || "(\uC751\uB2F5 \uC5C6\uC74C)"}

## \uCD5C\uADFC \uD788\uC2A4\uD1A0\uB9AC \uC8FC\uC785

${formatCodeBlock(record.historyContext)}

## \uC2E4\uD589 \uBA85\uB839\uC5B4 \uBBF8\uB9AC\uBCF4\uAE30

${formatCodeBlock(record.previewCommand, "sh")}

## \uC791\uC5C5 \uC804 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4

${formatWorkspaceSnapshot(record.workspaceBefore)}

## \uC791\uC5C5 \uD6C4 \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4

${formatWorkspaceSnapshot(record.workspaceAfter)}

## \uC6CC\uD06C\uC2A4\uD398\uC774\uC2A4 \uBCC0\uD654

${formatWorkspaceDelta(record.workspaceDelta)}${renderSections(record.extraSections)}
`;
  fs.writeFileSync(filePath, markdown, "utf8");
  appendHistoryIndex(paths, `${record.scope} | ${record.service} | ${record.title}`, path.relative(paths.rootDir, filePath));
  return filePath;
}
function writeServiceChangeHistory(paths, previousService, nextService, historyContext) {
  const baseName = `${getFileTimestamp()}-service-change`;
  const filePath = getAvailableFilePath(paths.servicesDir, baseName, ".md");
  const markdown = `# Service Change

- \uC2DC\uAC01: ${getHumanReadableNow()}
- \uC774\uC804 \uC11C\uBE44\uC2A4: \`${previousService || "(\uC5C6\uC74C)"}\`
- \uB2E4\uC74C \uC11C\uBE44\uC2A4: \`${nextService}\`

## \uC8FC\uC785 \uC608\uC815 \uD788\uC2A4\uD1A0\uB9AC

${formatCodeBlock(historyContext)}
`;
  fs.writeFileSync(filePath, markdown, "utf8");
  appendHistoryIndex(paths, `service-change | ${previousService || "(\uC5C6\uC74C)"} -> ${nextService}`, path.relative(paths.rootDir, filePath));
  return filePath;
}
function writeTestReport(paths, title, markdown) {
  const filePath = getAvailableFilePath(paths.testDir, `${getFileTimestamp()}-test`, ".md");
  const content = `# ${title}

- \uC2DC\uAC01: ${getHumanReadableNow()}

${markdown}
`;
  fs.writeFileSync(filePath, content, "utf8");
  return filePath;
}
function writeErrorReport(paths, error, options) {
  const filePath = getAvailableFilePath(paths.errorDir, `${getFileTimestamp()}-error`, ".md");
  const serializedError = serializeError(error);
  const traceMessages = options.traceMessages ?? [];
  const markdown = `# Error Report

- \uC2DC\uAC01: ${getHumanReadableNow()}
- scope: \`${options.scope}\`
- \uC791\uC5C5 \uACBD\uB85C: \`${paths.rootDir}\`
- \uC2E4\uD589 \uC778\uC790: \`${JSON.stringify(options.args ?? process.argv.slice(2))}\`

## Summary

${serializedError.summary || "Unknown error"}

## Error

\`\`\`json
${JSON.stringify(serializedError, null, 2)}
\`\`\`

## Trace

\`\`\`json
${JSON.stringify(traceMessages, null, 2)}
\`\`\`${renderSections(options.extraSections)}
`;
  fs.writeFileSync(filePath, markdown, "utf8");
  return filePath;
}
function ensureOutputDirectory(rootDir, outputPath) {
  const resolvedPath = path.resolve(rootDir, outputPath);
  fs.mkdirSync(resolvedPath, { recursive: true });
  return resolvedPath;
}

export { ensureOutputDirectory, openReportInBrowser, writeCodeReviewDiffFile, writeCodeReviewReport, writeErrorReport, writeServiceChangeHistory, writeTestReport, writeTurnHistory };
