import {
  ensureEnvLine,
  readEnvValue
} from "./chunk-YPXI7Q2M.js";

// src/db/vault-crypto.ts
import crypto from "crypto";
import fs from "fs";
import path from "path";
var ALGO = "aes-256-gcm";
var KEY_LEN = 32;
var IV_LEN = 12;
var TAG_LEN = 16;
var VERSION_PREFIX = "enc:v1:";
var cachedKey = null;
function findEnvPath() {
  let dir = process.cwd();
  for (let i = 0; i < 6; i++) {
    const candidate = path.join(dir, ".env");
    if (fs.existsSync(candidate)) return candidate;
    const parent = path.dirname(dir);
    if (parent === dir) break;
    dir = parent;
  }
  return path.resolve(process.cwd(), ".env");
}
function loadOrGenerateKey() {
  if (cachedKey) return cachedKey;
  const fromEnv = process.env.VAULT_ENCRYPTION_KEY;
  if (fromEnv) {
    const key = Buffer.from(fromEnv, "hex");
    if (key.length !== KEY_LEN) {
      throw new Error(`VAULT_ENCRYPTION_KEY must be ${KEY_LEN * 2} hex chars (${KEY_LEN} bytes)`);
    }
    cachedKey = key;
    return key;
  }
  const envPath = findEnvPath();
  try {
    const fromFile = readEnvValue(envPath, "VAULT_ENCRYPTION_KEY");
    if (fromFile) {
      const key = Buffer.from(fromFile, "hex");
      if (key.length !== KEY_LEN) {
        throw new Error(`VAULT_ENCRYPTION_KEY in ${envPath} must be ${KEY_LEN * 2} hex chars`);
      }
      process.env.VAULT_ENCRYPTION_KEY = fromFile;
      cachedKey = key;
      return key;
    }
  } catch {
  }
  const keyFile = process.env.VAULT_ENCRYPTION_KEY_FILE;
  if (keyFile) {
    try {
      if (fs.existsSync(keyFile)) {
        const hex3 = fs.readFileSync(keyFile, "utf-8").trim();
        const key = Buffer.from(hex3, "hex");
        if (key.length !== KEY_LEN) {
          throw new Error(`${keyFile} must contain ${KEY_LEN * 2} hex chars`);
        }
        process.env.VAULT_ENCRYPTION_KEY = hex3;
        cachedKey = key;
        return key;
      }
      const newKey2 = crypto.randomBytes(KEY_LEN);
      const hex2 = newKey2.toString("hex");
      fs.mkdirSync(path.dirname(keyFile), { recursive: true });
      fs.writeFileSync(keyFile, hex2, { mode: 384 });
      console.log(`[vault] generated VAULT_ENCRYPTION_KEY and wrote to ${keyFile}`);
      console.warn(`[vault] BACK UP ${keyFile} \u2014 losing this key makes vault entries unrecoverable`);
      process.env.VAULT_ENCRYPTION_KEY = hex2;
      cachedKey = newKey2;
      return newKey2;
    } catch (err) {
      const msg = err instanceof Error ? err.message : String(err);
      throw new Error(`[vault] Cannot read/write VAULT_ENCRYPTION_KEY_FILE (${keyFile}): ${msg}`);
    }
  }
  const newKey = crypto.randomBytes(KEY_LEN);
  const hex = newKey.toString("hex");
  try {
    ensureEnvLine(envPath, "VAULT_ENCRYPTION_KEY", hex);
    console.log(`[vault] generated VAULT_ENCRYPTION_KEY and wrote to ${envPath}`);
    console.warn(`[vault] BACK UP YOUR .env \u2014 losing this key will make all vault entries unrecoverable`);
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    throw new Error(
      `[vault] Cannot write VAULT_ENCRYPTION_KEY to ${envPath}: ${msg}
Set VAULT_ENCRYPTION_KEY manually in your environment:
  VAULT_ENCRYPTION_KEY=$(openssl rand -hex 32)
Or use VAULT_ENCRYPTION_KEY_FILE=<path> for a persistent on-disk key file.
Without a persistent key, vault entries would be unrecoverable on restart.`
    );
  }
  process.env.VAULT_ENCRYPTION_KEY = hex;
  cachedKey = newKey;
  return newKey;
}
function encryptValue(plaintext) {
  const key = loadOrGenerateKey();
  const iv = crypto.randomBytes(IV_LEN);
  const cipher = crypto.createCipheriv(ALGO, key, iv);
  const encrypted = Buffer.concat([cipher.update(plaintext, "utf8"), cipher.final()]);
  const tag = cipher.getAuthTag();
  const combined = Buffer.concat([iv, tag, encrypted]);
  return VERSION_PREFIX + combined.toString("base64");
}
function decryptValue(stored) {
  if (!stored.startsWith(VERSION_PREFIX)) return stored;
  const key = loadOrGenerateKey();
  const combined = Buffer.from(stored.slice(VERSION_PREFIX.length), "base64");
  const iv = combined.subarray(0, IV_LEN);
  const tag = combined.subarray(IV_LEN, IV_LEN + TAG_LEN);
  const ciphertext = combined.subarray(IV_LEN + TAG_LEN);
  const decipher = crypto.createDecipheriv(ALGO, key, iv);
  decipher.setAuthTag(tag);
  const decrypted = Buffer.concat([decipher.update(ciphertext), decipher.final()]);
  return decrypted.toString("utf8");
}

export {
  encryptValue,
  decryptValue
};
