import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync, statSync } from "node:fs";
import { join, dirname } from "node:path";
import { homedir } from "node:os";
import { randomBytes } from "node:crypto";
const PERSISTED_CONFIG_VERSION = 1;
const SETTINGS_SECRETS_DENYLIST = /* @__PURE__ */ new Set(["braveApiKey", "githubToken"]);
const CONFIG_FILE_MODE = 384;
const MAX_CONFIG_BYTES = 1e6;
let _cache = null;
let _cachePath = null;
function resetPersistedConfig() {
  _cache = null;
  _cachePath = null;
}
function sanitizeProvider(raw) {
  if (typeof raw !== "object" || raw === null) return void 0;
  const obj = raw;
  if (typeof obj.name !== "string") return void 0;
  const keyLocation = obj.keyLocation === "keychain" || obj.keyLocation === "file" || obj.keyLocation === "env" ? obj.keyLocation : "env";
  return { name: obj.name, keyLocation };
}
function migrateToV1(raw) {
  const { version: _v, settings: _s, provider: _p, ...rest } = raw;
  const existingSettings = typeof _s === "object" && _s !== null ? _s : {};
  const provider = sanitizeProvider(_p);
  return {
    version: PERSISTED_CONFIG_VERSION,
    settings: { ...rest, ...existingSettings },
    ...provider ? { provider } : {}
  };
}
function parseAndMigrate(raw) {
  const rawVersion = typeof raw.version === "number" ? raw.version : void 0;
  if (rawVersion === void 0) {
    return migrateToV1(raw);
  }
  if (rawVersion > PERSISTED_CONFIG_VERSION) {
    const settings2 = typeof raw.settings === "object" && raw.settings !== null ? raw.settings : {};
    const result2 = { version: rawVersion, settings: settings2 };
    const provider2 = sanitizeProvider(raw.provider);
    if (provider2) result2.provider = provider2;
    return result2;
  }
  if (rawVersion < PERSISTED_CONFIG_VERSION) {
    return migrateToV1(raw);
  }
  const settings = typeof raw.settings === "object" && raw.settings !== null ? raw.settings : {};
  const result = { version: rawVersion, settings };
  const provider = sanitizeProvider(raw.provider);
  if (provider) result.provider = provider;
  return result;
}
function atomicWrite(configPath, cfg) {
  const dir2 = dirname(configPath);
  mkdirSync(dir2, { recursive: true });
  const tmp = join(dir2, `.config-${randomBytes(6).toString("hex")}.tmp`);
  writeFileSync(tmp, JSON.stringify(cfg, null, 2), { mode: CONFIG_FILE_MODE });
  renameSync(tmp, configPath);
}
function readPersistedConfig(configPath) {
  if (_cache !== null && _cachePath === configPath) return _cache;
  if (!existsSync(configPath)) {
    _cache = { version: PERSISTED_CONFIG_VERSION, settings: {} };
    _cachePath = configPath;
    return _cache;
  }
  try {
    if (statSync(configPath).size > MAX_CONFIG_BYTES) {
      process.stderr.write(
        `[wigolo] config.json at ${configPath} exceeds ${MAX_CONFIG_BYTES} bytes; ignoring it.
`
      );
      _cache = { version: PERSISTED_CONFIG_VERSION, settings: {} };
      _cachePath = configPath;
      return _cache;
    }
  } catch {
  }
  let raw;
  try {
    raw = JSON.parse(readFileSync(configPath, "utf-8"));
  } catch {
    _cache = { version: PERSISTED_CONFIG_VERSION, settings: {} };
    _cachePath = configPath;
    return _cache;
  }
  const rawVersion = typeof raw.version === "number" ? raw.version : void 0;
  if (rawVersion !== void 0 && rawVersion > PERSISTED_CONFIG_VERSION) {
    process.stderr.write(
      `[wigolo] config.json version ${rawVersion} is newer than this build supports (${PERSISTED_CONFIG_VERSION}); reading known fields only.
`
    );
  }
  const parsed = parseAndMigrate(raw);
  const wasUpgraded = rawVersion === void 0 || rawVersion < PERSISTED_CONFIG_VERSION;
  if (wasUpgraded) {
    try {
      atomicWrite(configPath, parsed);
    } catch {
    }
  }
  _cache = parsed;
  _cachePath = configPath;
  return _cache;
}
function writePersistedConfig(configPath, patch) {
  const current = readPersistedConfig(configPath);
  const patchSettings = {};
  for (const [k, v] of Object.entries(patch.settings ?? {})) {
    if (SETTINGS_SECRETS_DENYLIST.has(k)) continue;
    patchSettings[k] = v;
  }
  const merged = {
    version: PERSISTED_CONFIG_VERSION,
    settings: { ...current.settings, ...patchSettings }
  };
  const provider = sanitizeProvider(patch.provider ?? current.provider);
  if (provider) merged.provider = provider;
  atomicWrite(configPath, merged);
  _cache = merged;
  _cachePath = configPath;
}
function defaultConfigPath() {
  return process.env.WIGOLO_CONFIG_PATH ?? join(homedir(), ".wigolo", "config.json");
}
export {
  PERSISTED_CONFIG_VERSION,
  SETTINGS_SECRETS_DENYLIST,
  defaultConfigPath,
  readPersistedConfig,
  resetPersistedConfig,
  writePersistedConfig
};
//# sourceMappingURL=persisted-config.js.map