import { describe, it, expect } from 'vitest';
import { encrypt, decrypt, generateEncryptionKey } from './crypto.js';

describe('crypto', () => {
  const masterKey = 'test-master-key-for-unit-tests';

  describe('encrypt / decrypt round-trip', () => {
    it('should encrypt and decrypt a simple string', () => {
      const plaintext = 'hello-world-token';
      const encrypted = encrypt(plaintext, masterKey);
      const decrypted = decrypt(encrypted, masterKey);
      expect(decrypted).toBe(plaintext);
    });

    it('should produce different ciphertext for the same input (random IV)', () => {
      const plaintext = 'same-input';
      const a = encrypt(plaintext, masterKey);
      const b = encrypt(plaintext, masterKey);
      expect(a).not.toBe(b);
    });

    it('should handle empty string', () => {
      const encrypted = encrypt('', masterKey);
      expect(decrypt(encrypted, masterKey)).toBe('');
    });

    it('should handle unicode content', () => {
      const plaintext = 'Türkçe içerik 🎉 日本語';
      const encrypted = encrypt(plaintext, masterKey);
      expect(decrypt(encrypted, masterKey)).toBe(plaintext);
    });
  });

  describe('decrypt error handling', () => {
    it('should throw on invalid format', () => {
      expect(() => decrypt('not-valid', masterKey)).toThrow('Invalid encrypted data format');
    });

    it('should throw on wrong master key', () => {
      const encrypted = encrypt('secret', masterKey);
      expect(() => decrypt(encrypted, 'wrong-key')).toThrow();
    });

    it('should throw on tampered ciphertext', () => {
      const encrypted = encrypt('secret', masterKey);
      const parts = encrypted.split(':');
      parts[2] = 'AAAA' + parts[2].slice(4); // tamper with encrypted data
      expect(() => decrypt(parts.join(':'), masterKey)).toThrow();
    });
  });

  describe('generateEncryptionKey', () => {
    it('should return a 64-char hex string (32 bytes)', () => {
      const key = generateEncryptionKey();
      expect(key).toHaveLength(64);
      expect(/^[0-9a-f]{64}$/.test(key)).toBe(true);
    });

    it('should produce unique keys', () => {
      const a = generateEncryptionKey();
      const b = generateEncryptionKey();
      expect(a).not.toBe(b);
    });
  });
});
