"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const vitest_1 = require("vitest");
const fs_1 = require("fs");
const os_1 = require("os");
const path_1 = require("path");
const fs_2 = require("fs");
const fs_3 = require("fs");
const encryption_js_1 = require("./encryption.js");
const crypto_js_1 = require("../../utils/crypto.js");
let tmpDir;
let store;
let masterKey;
(0, vitest_1.beforeEach)(() => {
    tmpDir = (0, fs_1.mkdtempSync)((0, path_1.join)((0, os_1.tmpdir)(), 'enc-store-test-'));
    masterKey = (0, crypto_js_1.generateEncryptionKey)();
    store = new encryption_js_1.EncryptedKeyStore(tmpDir, masterKey);
});
(0, vitest_1.afterEach)(() => {
    (0, fs_1.rmSync)(tmpDir, { recursive: true, force: true });
});
(0, vitest_1.describe)('EncryptedKeyStore.init', () => {
    (0, vitest_1.it)('should create the config directory and store file', async () => {
        await store.init();
        const filePath = (0, path_1.resolve)(tmpDir, 'config', 'api-keys.enc.json');
        (0, vitest_1.expect)((0, fs_2.existsSync)(filePath)).toBe(true);
        const content = JSON.parse((0, fs_3.readFileSync)(filePath, 'utf-8'));
        (0, vitest_1.expect)(content).toEqual({ version: 1, keys: {} });
    });
    (0, vitest_1.it)('should not overwrite existing store on re-init', async () => {
        await store.init();
        await store.setKey('test-key', 'test-value');
        await store.init();
        const value = await store.getKey('test-key');
        (0, vitest_1.expect)(value).toBe('test-value');
    });
});
(0, vitest_1.describe)('EncryptedKeyStore.setKey / getKey', () => {
    (0, vitest_1.it)('should encrypt and store a key, then decrypt on retrieval', async () => {
        await store.init();
        await store.setKey('OPENROUTER_API_KEY', 'sk-or-v1-abc123');
        const value = await store.getKey('OPENROUTER_API_KEY');
        (0, vitest_1.expect)(value).toBe('sk-or-v1-abc123');
    });
    (0, vitest_1.it)('should store encrypted data, not plaintext', async () => {
        await store.init();
        await store.setKey('SECRET', 'my-secret-value');
        const filePath = (0, path_1.resolve)(tmpDir, 'config', 'api-keys.enc.json');
        const raw = (0, fs_3.readFileSync)(filePath, 'utf-8');
        (0, vitest_1.expect)(raw).not.toContain('my-secret-value');
    });
    (0, vitest_1.it)('should return null for a non-existent key', async () => {
        await store.init();
        const value = await store.getKey('non-existent');
        (0, vitest_1.expect)(value).toBeNull();
    });
    (0, vitest_1.it)('should update an existing key and preserve createdAt', async () => {
        await store.init();
        await store.setKey('TOKEN', 'old-value');
        const filePath = (0, path_1.resolve)(tmpDir, 'config', 'api-keys.enc.json');
        const before = JSON.parse((0, fs_3.readFileSync)(filePath, 'utf-8'));
        const createdAt = before.keys['TOKEN'].createdAt;
        await store.setKey('TOKEN', 'new-value');
        const after = JSON.parse((0, fs_3.readFileSync)(filePath, 'utf-8'));
        (0, vitest_1.expect)(after.keys['TOKEN'].createdAt).toBe(createdAt);
        (0, vitest_1.expect)(after.keys['TOKEN'].updatedAt).not.toBe(createdAt);
        const value = await store.getKey('TOKEN');
        (0, vitest_1.expect)(value).toBe('new-value');
    });
});
(0, vitest_1.describe)('EncryptedKeyStore.deleteKey', () => {
    (0, vitest_1.it)('should delete an existing key and return true', async () => {
        await store.init();
        await store.setKey('TO_DELETE', 'value');
        const deleted = await store.deleteKey('TO_DELETE');
        (0, vitest_1.expect)(deleted).toBe(true);
        const value = await store.getKey('TO_DELETE');
        (0, vitest_1.expect)(value).toBeNull();
    });
    (0, vitest_1.it)('should return false when deleting a non-existent key', async () => {
        await store.init();
        const deleted = await store.deleteKey('nope');
        (0, vitest_1.expect)(deleted).toBe(false);
    });
});
(0, vitest_1.describe)('EncryptedKeyStore.listKeys', () => {
    (0, vitest_1.it)('should list keys with masked values showing last 4 chars', async () => {
        await store.init();
        await store.setKey('API_KEY', 'sk-or-v1-abcdef1234');
        await store.setKey('BOT_TOKEN', '123456:ABCdefGHIjklMNO');
        const keys = await store.listKeys();
        (0, vitest_1.expect)(keys).toHaveLength(2);
        const apiKey = keys.find(k => k.name === 'API_KEY');
        (0, vitest_1.expect)(apiKey).toBeDefined();
        (0, vitest_1.expect)(apiKey.maskedValue).toBe('****1234');
        (0, vitest_1.expect)(apiKey.createdAt).toBeTruthy();
        (0, vitest_1.expect)(apiKey.updatedAt).toBeTruthy();
        const botToken = keys.find(k => k.name === 'BOT_TOKEN');
        (0, vitest_1.expect)(botToken).toBeDefined();
        (0, vitest_1.expect)(botToken.maskedValue).toBe('****lMNO');
    });
    (0, vitest_1.it)('should mask short values as ****', async () => {
        await store.init();
        await store.setKey('SHORT', 'ab');
        const keys = await store.listKeys();
        const short = keys.find(k => k.name === 'SHORT');
        (0, vitest_1.expect)(short.maskedValue).toBe('****');
    });
    (0, vitest_1.it)('should return empty array when no keys exist', async () => {
        await store.init();
        const keys = await store.listKeys();
        (0, vitest_1.expect)(keys).toEqual([]);
    });
});
(0, vitest_1.describe)('EncryptedKeyStore.hasKey', () => {
    (0, vitest_1.it)('should return true for existing key', async () => {
        await store.init();
        await store.setKey('EXISTS', 'value');
        (0, vitest_1.expect)(await store.hasKey('EXISTS')).toBe(true);
    });
    (0, vitest_1.it)('should return false for non-existent key', async () => {
        await store.init();
        (0, vitest_1.expect)(await store.hasKey('NOPE')).toBe(false);
    });
});
(0, vitest_1.describe)('EncryptedKeyStore error handling', () => {
    (0, vitest_1.it)('should throw when masterKey is empty on setKey', async () => {
        const noKeyStore = new encryption_js_1.EncryptedKeyStore(tmpDir, '');
        await noKeyStore.init();
        await (0, vitest_1.expect)(noKeyStore.setKey('k', 'v')).rejects.toThrow('ENCRYPTION_KEY is not configured');
    });
    (0, vitest_1.it)('should throw when masterKey is empty on getKey', async () => {
        const noKeyStore = new encryption_js_1.EncryptedKeyStore(tmpDir, '');
        await noKeyStore.init();
        await (0, vitest_1.expect)(noKeyStore.getKey('k')).rejects.toThrow('ENCRYPTION_KEY is not configured');
    });
    (0, vitest_1.it)('should throw when masterKey is empty on listKeys', async () => {
        const noKeyStore = new encryption_js_1.EncryptedKeyStore(tmpDir, '');
        await noKeyStore.init();
        await (0, vitest_1.expect)(noKeyStore.listKeys()).rejects.toThrow('ENCRYPTION_KEY is not configured');
    });
    (0, vitest_1.it)('should fail to decrypt with wrong master key', async () => {
        await store.init();
        await store.setKey('SECURE', 'secret-data');
        const wrongKeyStore = new encryption_js_1.EncryptedKeyStore(tmpDir, (0, crypto_js_1.generateEncryptionKey)());
        await (0, vitest_1.expect)(wrongKeyStore.getKey('SECURE')).rejects.toThrow();
    });
});
//# sourceMappingURL=encryption.test.js.map