/**
 * InternalAppEnvCryptoService Unit Tests
 *
 * 覆盖 AES-GCM 加密 round-trip 正确性 + 篡改检测 + mask 行为
 * 06-data-model.md §2.4 + 07-api §3.4 不变量。
 */

import { ConfigService } from '@nestjs/config';
import { InternalAppEnvCryptoService } from '@/modules/internal-app-platform/services/env-crypto.service';

describe('InternalAppEnvCryptoService', () => {
  let svc: InternalAppEnvCryptoService;

  beforeEach(() => {
    const config = {
      get: (key: string) =>
        key === 'INTERNAL_APP_ENV_MASTER_KEY' ? 'test-master-key-12345' : undefined,
    } as ConfigService;
    svc = new InternalAppEnvCryptoService(config);
  });

  describe('encrypt / decrypt round-trip', () => {
    it('简单 ASCII 字符串', () => {
      const { encrypted, iv, kmsKeyVersion } = svc.encrypt('sk-1234567890abcdef');
      expect(kmsKeyVersion).toBe(1);
      expect(iv).toHaveLength(12);
      expect(encrypted.length).toBeGreaterThan(16); // 至少 ciphertext + 16B authTag
      const decrypted = svc.decrypt(encrypted, iv, kmsKeyVersion);
      expect(decrypted).toBe('sk-1234567890abcdef');
    });

    it('UTF-8 中文', () => {
      const plaintext = '密钥包含中文字符 + emoji 🔑';
      const { encrypted, iv, kmsKeyVersion } = svc.encrypt(plaintext);
      const decrypted = svc.decrypt(encrypted, iv, kmsKeyVersion);
      expect(decrypted).toBe(plaintext);
    });

    it('空字符串', () => {
      const { encrypted, iv, kmsKeyVersion } = svc.encrypt('');
      const decrypted = svc.decrypt(encrypted, iv, kmsKeyVersion);
      expect(decrypted).toBe('');
    });

    it('每次加密 IV 不同（语义安全）', () => {
      const r1 = svc.encrypt('same-plaintext');
      const r2 = svc.encrypt('same-plaintext');
      expect(Buffer.compare(r1.iv, r2.iv)).not.toBe(0);
      expect(Buffer.compare(r1.encrypted, r2.encrypted)).not.toBe(0);
    });
  });

  describe('篡改检测（GCM authTag）', () => {
    it('密文最后一位被改 → decrypt 抛错', () => {
      const { encrypted, iv, kmsKeyVersion } = svc.encrypt('secret');
      const tampered = Buffer.from(encrypted);
      tampered[tampered.length - 1] ^= 0xff;
      expect(() => svc.decrypt(tampered, iv, kmsKeyVersion)).toThrow();
    });

    it('IV 被改 → decrypt 抛错', () => {
      const { encrypted, iv, kmsKeyVersion } = svc.encrypt('secret');
      const tamperedIv = Buffer.from(iv);
      tamperedIv[0] ^= 0xff;
      expect(() => svc.decrypt(encrypted, tamperedIv, kmsKeyVersion)).toThrow();
    });
  });

  describe('maskValue', () => {
    it('短串（≤4 字符）全 mask', () => {
      expect(svc.maskValue('')).toBe('****');
      expect(svc.maskValue('ab')).toBe('****');
      expect(svc.maskValue('abcd')).toBe('****');
    });

    it('长串显示前 4 字符', () => {
      expect(svc.maskValue('sk-abc1234')).toBe('sk-a****');
      expect(svc.maskValue('AKIA1234567890')).toBe('AKIA****');
    });
  });
});
