import { describe, expect, it } from 'vitest';
import { encryptField, decryptField, InvalidEncryptionKeyError, } from '../../security/encrypted-fields.js';
const VALID_KEY = 'a'.repeat(64); // 64 hex chars = 32 bytes
const ALT_KEY = 'b'.repeat(64);
describe('encrypted-fields key validation', () => {
    it('rejects empty key', async () => {
        await expect(encryptField('hello', '')).rejects.toBeInstanceOf(InvalidEncryptionKeyError);
    });
    it('rejects undefined / non-string key', async () => {
        await expect(encryptField('hello', undefined)).rejects.toBeInstanceOf(InvalidEncryptionKeyError);
    });
    it('rejects too-short key', async () => {
        await expect(encryptField('hello', 'a'.repeat(32))).rejects.toBeInstanceOf(InvalidEncryptionKeyError);
    });
    it('rejects too-long key', async () => {
        await expect(encryptField('hello', 'a'.repeat(128))).rejects.toBeInstanceOf(InvalidEncryptionKeyError);
    });
    it('rejects non-hex characters', async () => {
        await expect(encryptField('hello', 'z'.repeat(63) + 'a')).rejects.toBeInstanceOf(InvalidEncryptionKeyError);
    });
    it('rejects the placeholder dev key from the .env example', async () => {
        // "aes256-local-dev-key-change-in-prod" is 35 chars, not 64, and contains '-'.
        await expect(encryptField('hello', 'aes256-local-dev-key-change-in-prod')).rejects.toBeInstanceOf(InvalidEncryptionKeyError);
    });
    it('error message points operators at the random-bytes generator', async () => {
        try {
            await encryptField('hello', 'short');
            throw new Error('should have thrown');
        }
        catch (err) {
            expect(err).toBeInstanceOf(InvalidEncryptionKeyError);
            expect(err.message).toContain('randomBytes(32)');
        }
    });
});
describe('encrypted-fields round-trip', () => {
    it('encrypts and decrypts with the same key', async () => {
        const plaintext = 'hello, world — with unicode ✓';
        const encrypted = await encryptField(plaintext, VALID_KEY);
        expect(encrypted).not.toBe(plaintext);
        const decrypted = await decryptField(encrypted, VALID_KEY);
        expect(decrypted).toBe(plaintext);
    });
    it('produces different ciphertext on every call (unique IV)', async () => {
        const a = await encryptField('same input', VALID_KEY);
        const b = await encryptField('same input', VALID_KEY);
        expect(a).not.toBe(b);
    });
    it('rejects ciphertext encrypted with a different key', async () => {
        const encrypted = await encryptField('secret', VALID_KEY);
        await expect(decryptField(encrypted, ALT_KEY)).rejects.toThrow();
    });
    it('rejects tampered ciphertext (AES-GCM auth tag enforces integrity)', async () => {
        const encrypted = await encryptField('secret', VALID_KEY);
        // Flip one byte at the end (inside the auth tag region)
        const tampered = encrypted.slice(0, -2) + (encrypted.slice(-2) === 'ff' ? '00' : 'ff');
        await expect(decryptField(tampered, VALID_KEY)).rejects.toThrow();
    });
});
//# sourceMappingURL=encrypted-fields.test.js.map