import { existsSync, readFileSync, readdirSync, rmSync } from 'node:fs';
import { CCJK_CONFIG_DIR } from '../chunks/constants.mjs';
import { writeFileAtomic, ensureDir } from '../chunks/fs-operations.mjs';
import { j as join, b as basename } from './ccjk.bQ7Dh1g4.mjs';

const SNAPSHOTS_DIR = join(CCJK_CONFIG_DIR, "snapshots");
function getSnapshotsDir() {
  return process.env.CCJK_SNAPSHOTS_DIR || SNAPSHOTS_DIR;
}
function safeTimestamp(date = /* @__PURE__ */ new Date()) {
  return date.toISOString().replace(/[:.]/g, "-");
}
function safeFileName(path) {
  return basename(path).replace(/[^\w.-]/g, "_") || "config";
}
function createConfigSnapshot(plan) {
  const id = `${safeTimestamp()}-${plan.id.slice(0, 8)}`;
  const snapshotDir = join(getSnapshotsDir(), id);
  const filesDir = join(snapshotDir, "files");
  ensureDir(filesDir);
  const seen = /* @__PURE__ */ new Map();
  const files = [];
  for (const change of plan.changes) {
    const beforeContent = change.beforeContent ?? "";
    const count = seen.get(change.file) ?? 0;
    seen.set(change.file, count + 1);
    const backupName = `${String(count + 1).padStart(2, "0")}-${safeFileName(change.file)}`;
    const backupPath = join("files", backupName);
    writeFileAtomic(join(snapshotDir, backupPath), beforeContent);
    files.push({
      target: change.target,
      sourcePath: change.file,
      backupPath,
      beforeHash: change.beforeHash,
      afterHash: change.afterHash,
      operation: change.operation,
      reason: change.reason,
      existed: change.beforeExists
    });
  }
  const manifest = {
    version: 1,
    id,
    planId: plan.id,
    title: plan.title,
    createdAt: (/* @__PURE__ */ new Date()).toISOString(),
    risk: plan.risk,
    files
  };
  writeFileAtomic(join(snapshotDir, "manifest.json"), JSON.stringify(manifest, null, 2));
  return {
    id,
    path: snapshotDir,
    manifest
  };
}
function listConfigSnapshots() {
  const snapshotsDir = getSnapshotsDir();
  if (!existsSync(snapshotsDir)) {
    return [];
  }
  return readdirSync(snapshotsDir).map((entry) => {
    const manifestPath = join(snapshotsDir, entry, "manifest.json");
    try {
      return JSON.parse(readFileSync(manifestPath, "utf-8"));
    } catch {
      return null;
    }
  }).filter((item) => Boolean(item)).sort((a, b) => b.createdAt.localeCompare(a.createdAt));
}
function readConfigSnapshot(id) {
  const snapshotDir = join(getSnapshotsDir(), id);
  const manifestPath = join(snapshotDir, "manifest.json");
  if (!existsSync(manifestPath)) {
    return null;
  }
  try {
    const manifest = JSON.parse(readFileSync(manifestPath, "utf-8"));
    return {
      id: manifest.id,
      path: snapshotDir,
      manifest
    };
  } catch {
    return null;
  }
}
function restoreConfigSnapshot(id) {
  const snapshot = readConfigSnapshot(id);
  if (!snapshot) {
    throw new Error(`Snapshot not found: ${id}`);
  }
  const restored = [];
  const skipped = [];
  for (const file of snapshot.manifest.files) {
    const backupPath = join(snapshot.path, file.backupPath);
    if (!existsSync(backupPath)) {
      skipped.push(file);
      continue;
    }
    if (!file.existed) {
      if (existsSync(file.sourcePath)) {
        rmSync(file.sourcePath, { force: true });
      }
      restored.push(file);
      continue;
    }
    const content = readFileSync(backupPath, "utf-8");
    writeFileAtomic(file.sourcePath, content);
    restored.push(file);
  }
  return { restored, skipped };
}

export { restoreConfigSnapshot as a, createConfigSnapshot as c, listConfigSnapshots as l, readConfigSnapshot as r };
