import { SecretCryptoService } from '../src/modules/netaclaw/service/secret_crypto.js';

describe('SecretCryptoService', () => {
  const originalNetaSecretKey = process.env.NETA_SECRET_KEY;
  const originalAppSecret = process.env.APP_SECRET;

  beforeEach(() => {
    process.env.NETA_SECRET_KEY = 'test-secret-key';
    delete process.env.APP_SECRET;
  });

  afterEach(() => {
    if (originalNetaSecretKey === undefined) {
      delete process.env.NETA_SECRET_KEY;
    } else {
      process.env.NETA_SECRET_KEY = originalNetaSecretKey;
    }

    if (originalAppSecret === undefined) {
      delete process.env.APP_SECRET;
    } else {
      process.env.APP_SECRET = originalAppSecret;
    }
  });

  it('encrypts and decrypts text without embedding plaintext', () => {
    const service = new SecretCryptoService();

    const encrypted = service.encryptText('mysql-password');

    expect(encrypted).not.toContain('mysql-password');
    expect(service.decryptText(encrypted)).toBe('mysql-password');
  });

  it('encrypts and decrypts JSON values', () => {
    const service = new SecretCryptoService();
    const value = { username: 'readonly', scopes: ['order.read'], maxRows: 100 };

    const encrypted = service.encryptJson(value);

    expect(encrypted).not.toContain('readonly');
    expect(service.decryptJson<typeof value>(encrypted)).toEqual(value);
  });

  it('uses configured jwt secret when secret env vars are absent', () => {
    delete process.env.NETA_SECRET_KEY;
    delete process.env.APP_SECRET;
    const service = new SecretCryptoService();
    (service as any).jwtSecret = 'configured-jwt-secret';

    const encrypted = service.encryptText('mysql-password');

    expect(service.decryptText(encrypted)).toBe('mysql-password');
  });

  it('rejects tampered envelopes', () => {
    const service = new SecretCryptoService();
    const encrypted = service.encryptText('mysql-password');
    const envelope = JSON.parse(Buffer.from(encrypted, 'base64').toString('utf8'));
    envelope.ct = `${envelope.ct.slice(0, -2)}AA`;
    const tampered = Buffer.from(JSON.stringify(envelope), 'utf8').toString('base64');

    expect(() => service.decryptText(tampered)).toThrow();
  });
});
