#!/usr/bin/env node
import {
  CONFIG_DIR_NAME,
  VERSION
} from "./chunk-KRU4DFRH.js";

// src/diagnostics/crash-log.ts
import {
  existsSync,
  mkdirSync,
  readdirSync,
  readFileSync,
  statSync,
  unlinkSync,
  writeFileSync
} from "fs";
import { join } from "path";
import { homedir, platform, release, arch } from "os";
var LOGS_DIR_NAME = "logs";
var CRASH_LOG_PREFIX = "crash-";
var MAX_CRASH_FILES = 20;
function getLogsDir(configDir) {
  const base = configDir ?? join(homedir(), CONFIG_DIR_NAME);
  return join(base, LOGS_DIR_NAME);
}
function ensureLogsDir(configDir) {
  const dir = getLogsDir(configDir);
  if (!existsSync(dir)) {
    mkdirSync(dir, { recursive: true });
  }
  return dir;
}
function isoTimestampForFilename(d = /* @__PURE__ */ new Date()) {
  return d.toISOString().replace(/[:.]/g, "-");
}
function writeCrashLog(err, context, configDir) {
  try {
    const dir = ensureLogsDir(configDir);
    const ts = /* @__PURE__ */ new Date();
    const file = join(dir, `${CRASH_LOG_PREFIX}${isoTimestampForFilename(ts)}.log`);
    const errMessage = err instanceof Error ? err.message : String(err);
    const errStack = err instanceof Error ? err.stack ?? "(no stack)" : "(non-Error thrown)";
    const lines = [
      `# ai-cli crash log`,
      `timestamp: ${ts.toISOString()}`,
      `kind:      ${context.kind}`,
      `version:   ${VERSION}`,
      `node:      ${process.version}`,
      `platform:  ${platform()} ${release()} (${arch()})`,
      `pid:       ${process.pid}`,
      context.provider ? `provider:  ${context.provider}` : "",
      context.model ? `model:     ${context.model}` : "",
      context.lastAction ? `lastAction: ${truncate(context.lastAction, 500)}` : "",
      "",
      `## message`,
      errMessage,
      "",
      `## stack`,
      errStack,
      ""
    ].filter(Boolean);
    writeFileSync(file, lines.join("\n"), "utf-8");
    pruneOldCrashes(configDir);
    return file;
  } catch {
    return null;
  }
}
function truncate(s, n) {
  return s.length <= n ? s : s.slice(0, n) + "\u2026";
}
function pruneOldCrashes(configDir) {
  try {
    const dir = getLogsDir(configDir);
    if (!existsSync(dir)) return;
    const entries = readdirSync(dir).filter((f) => f.startsWith(CRASH_LOG_PREFIX) && f.endsWith(".log")).map((f) => {
      const full = join(dir, f);
      let mtime = 0;
      try {
        mtime = statSync(full).mtimeMs;
      } catch {
      }
      return { file: full, mtime };
    }).sort((a, b) => b.mtime - a.mtime);
    for (const e of entries.slice(MAX_CRASH_FILES)) {
      try {
        unlinkSync(e.file);
      } catch {
      }
    }
  } catch {
  }
}
function listRecentCrashes(limit = 10, configDir) {
  const dir = getLogsDir(configDir);
  if (!existsSync(dir)) return [];
  const files = [];
  let names;
  try {
    names = readdirSync(dir);
  } catch {
    return [];
  }
  for (const name of names) {
    if (!name.startsWith(CRASH_LOG_PREFIX) || !name.endsWith(".log")) continue;
    const full = join(dir, name);
    try {
      const st = statSync(full);
      const head = readFileSync(full, "utf-8").split("\n").slice(0, 20);
      const tsLine = head.find((l) => l.startsWith("timestamp:"));
      const kindLine = head.find((l) => l.startsWith("kind:"));
      const msgIdx = head.findIndex((l) => l.trim() === "## message");
      const message = msgIdx >= 0 && head[msgIdx + 1] ? head[msgIdx + 1] : "";
      files.push({
        file: full,
        timestamp: tsLine ? tsLine.replace("timestamp:", "").trim() : st.mtime.toISOString(),
        kind: kindLine ? kindLine.replace("kind:", "").trim() : "unknown",
        message: truncate(message, 200),
        sizeBytes: st.size
      });
    } catch {
    }
  }
  files.sort((a, b) => a.timestamp < b.timestamp ? 1 : -1);
  return files.slice(0, limit);
}
function getConfigDirUsage(configDir) {
  const base = configDir ?? join(homedir(), CONFIG_DIR_NAME);
  if (!existsSync(base)) return { totalBytes: 0, entries: [] };
  const entries = [];
  let total = 0;
  let names;
  try {
    names = readdirSync(base);
  } catch {
    return { totalBytes: 0, entries: [] };
  }
  for (const name of names) {
    const full = join(base, name);
    const bytes = dirSize(full);
    entries.push({ name, bytes });
    total += bytes;
  }
  entries.sort((a, b) => b.bytes - a.bytes);
  return { totalBytes: total, entries };
}
function dirSize(path) {
  try {
    const st = statSync(path);
    if (st.isFile()) return st.size;
    if (!st.isDirectory()) return 0;
    let sum = 0;
    for (const name of readdirSync(path)) {
      sum += dirSize(join(path, name));
    }
    return sum;
  } catch {
    return 0;
  }
}

export {
  writeCrashLog,
  listRecentCrashes,
  getConfigDirUsage
};
