import { randomBytes, createCipheriv, createDecipheriv } from "node:crypto";
import { readFileSync, writeFileSync, existsSync } from "node:fs";
import { resolve } from "node:path";
import { homedir } from "node:os";
const ALGORITHM = "aes-256-gcm";
const KEY_LENGTH = 32; // 256 bits
const IV_LENGTH = 12; // 96 bits — recommended for GCM
const AUTH_TAG_LENGTH = 16; // 128 bits
/**
 * Resolve the config directory from brand.json (same pattern as anthropic-key, email).
 * Falls back to ".maxy" if brand.json is unreadable.
 */
function resolveConfigDir() {
    try {
        const platformRoot = process.env.PLATFORM_ROOT;
        if (platformRoot) {
            const brandPath = resolve(platformRoot, "config/brand.json");
            const brand = JSON.parse(readFileSync(brandPath, "utf-8"));
            if (brand.configDir)
                return brand.configDir;
        }
    }
    catch {
        // Fall back to default
    }
    return ".maxy";
}
function keyFilePath() {
    return resolve(homedir(), resolveConfigDir(), ".loop-encryption-key");
}
/**
 * Load or generate the encryption key. Generated on first use,
 * stored at ~/.{configDir}/.loop-encryption-key with mode 0o600.
 */
function loadOrGenerateKey() {
    const path = keyFilePath();
    if (existsSync(path)) {
        const hex = readFileSync(path, "utf-8").trim();
        const buf = Buffer.from(hex, "hex");
        if (buf.length !== KEY_LENGTH) {
            throw new Error(`Encryption key at ${path} is ${buf.length} bytes, expected ${KEY_LENGTH}. ` +
                `Delete the file and re-register all Loop team keys.`);
        }
        return buf;
    }
    // First use — generate a new key
    const key = randomBytes(KEY_LENGTH);
    writeFileSync(path, key.toString("hex"), { mode: 0o600 });
    console.error(`[loop] encryption key generated at ${path}`);
    return key;
}
/**
 * Encrypt a plaintext string. Returns "iv:ciphertext:authTag" (hex-encoded).
 */
export function encrypt(plaintext) {
    const key = loadOrGenerateKey();
    const iv = randomBytes(IV_LENGTH);
    const cipher = createCipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });
    let encrypted = cipher.update(plaintext, "utf-8", "hex");
    encrypted += cipher.final("hex");
    const authTag = cipher.getAuthTag().toString("hex");
    return `${iv.toString("hex")}:${encrypted}:${authTag}`;
}
/**
 * Decrypt a value produced by encrypt(). Expects "iv:ciphertext:authTag" (hex-encoded).
 * Throws on tampered/corrupt data or wrong key.
 */
export function decrypt(encryptedValue) {
    const parts = encryptedValue.split(":");
    if (parts.length !== 3) {
        throw new Error("Malformed encrypted value — expected iv:ciphertext:authTag");
    }
    const [ivHex, ciphertextHex, authTagHex] = parts;
    const path = keyFilePath();
    if (!existsSync(path)) {
        throw new Error(`Encryption key not found at ${path}. ` +
            `All stored Loop API keys are unrecoverable. Re-register keys.`);
    }
    const key = loadOrGenerateKey();
    const iv = Buffer.from(ivHex, "hex");
    const authTag = Buffer.from(authTagHex, "hex");
    const decipher = createDecipheriv(ALGORITHM, key, iv, { authTagLength: AUTH_TAG_LENGTH });
    decipher.setAuthTag(authTag);
    let decrypted = decipher.update(ciphertextHex, "hex", "utf-8");
    decrypted += decipher.final("utf-8");
    return decrypted;
}
//# sourceMappingURL=crypto.js.map