import { validateEnv, validateJwtSecret } from '../env-validation';

describe('validateJwtSecret', () => {
  it('rejects known placeholder values (case-insensitive)', () => {
    const placeholders = [
      'CHANGE_ME',
      'change_me',
      'Change_Me',
      'changeme',
      'your_jwt_secret',
      'your_jwt_secret_change_me',
      'secret',
      'supersecret',
      'password',
      'test',
      'default',
      'placeholder',
      'replace_me',
      'fixme',
      'todo',
      'xxx',
    ];

    for (const value of placeholders) {
      const error = validateJwtSecret('JWT_SECRET', value);
      expect(error).not.toBeNull();
      expect(error).toContain('placeholder');
    }
  });

  it('rejects secrets shorter than 32 characters', () => {
    const error = validateJwtSecret('JWT_SECRET', 'short-but-not-placeholder');
    expect(error).not.toBeNull();
    expect(error).toContain('too short');
    expect(error).toContain('minimum 32');
  });

  it('accepts valid secrets of sufficient length', () => {
    const validSecret = 'a-randomly-generated-secret-that-is-definitely-long-enough-for-production';
    const error = validateJwtSecret('JWT_SECRET', validSecret);
    expect(error).toBeNull();
  });

  it('accepts exactly 32-character secrets', () => {
    const error = validateJwtSecret('JWT_SECRET', 'abcdefghijklmnopqrstuvwxyz012345');
    expect(error).toBeNull();
  });

  it('includes the key name in error messages', () => {
    const error = validateJwtSecret('JWT_REFRESH_SECRET', 'CHANGE_ME');
    expect(error).toContain('JWT_REFRESH_SECRET');
  });
});

describe('validateEnv', () => {
  const originalEnv = process.env;

  beforeEach(() => {
    process.env = { ...originalEnv };
  });

  afterAll(() => {
    process.env = originalEnv;
  });

  const VALID_SECRET = 'a-valid-random-secret-with-at-least-32-characters-for-tests';
  const VALID_REFRESH_SECRET = 'another-valid-random-secret-at-least-32-characters-long!!';

  function setValidJwtSecrets() {
    process.env['JWT_SECRET'] = VALID_SECRET;
    process.env['JWT_REFRESH_SECRET'] = VALID_REFRESH_SECRET;
  }

  it('throws when JWT_SECRET is missing', () => {
    delete process.env['JWT_SECRET'];
    process.env['JWT_REFRESH_SECRET'] = VALID_REFRESH_SECRET;

    expect(() => validateEnv()).toThrow('Missing required environment variables');
    expect(() => validateEnv()).toThrow('JWT_SECRET');
  });

  it('throws when JWT_REFRESH_SECRET is missing', () => {
    process.env['JWT_SECRET'] = VALID_SECRET;
    delete process.env['JWT_REFRESH_SECRET'];

    expect(() => validateEnv()).toThrow('Missing required environment variables');
    expect(() => validateEnv()).toThrow('JWT_REFRESH_SECRET');
  });

  it('throws when both JWT secrets are missing', () => {
    delete process.env['JWT_SECRET'];
    delete process.env['JWT_REFRESH_SECRET'];

    expect(() => validateEnv()).toThrow('Missing required environment variables');
  });

  it('throws when JWT_SECRET is a placeholder value', () => {
    process.env['JWT_SECRET'] = 'CHANGE_ME';
    process.env['JWT_REFRESH_SECRET'] = VALID_REFRESH_SECRET;

    expect(() => validateEnv()).toThrow('Insecure JWT secret configuration');
    expect(() => validateEnv()).toThrow('placeholder');
  });

  it('throws when JWT_SECRET is too short', () => {
    process.env['JWT_SECRET'] = 'short';
    process.env['JWT_REFRESH_SECRET'] = VALID_REFRESH_SECRET;

    expect(() => validateEnv()).toThrow('Insecure JWT secret configuration');
    expect(() => validateEnv()).toThrow('too short');
  });

  it('throws when JWT_REFRESH_SECRET is a placeholder value', () => {
    process.env['JWT_SECRET'] = VALID_SECRET;
    process.env['JWT_REFRESH_SECRET'] = 'CHANGE_ME';

    expect(() => validateEnv()).toThrow('Insecure JWT secret configuration');
  });

  it('does not throw with valid secrets in development', () => {
    process.env['NODE_ENV'] = 'development';
    setValidJwtSecrets();

    expect(() => validateEnv()).not.toThrow();
  });

  it('throws in production when DATABASE_URL is missing', () => {
    process.env['NODE_ENV'] = 'production';
    setValidJwtSecrets();
    delete process.env['DATABASE_URL'];
    process.env['CORS_ORIGINS'] = 'https://goodgo.vn';
    process.env['REDIS_HOST'] = 'redis.internal';

    expect(() => validateEnv()).toThrow('Missing required environment variables in production');
    expect(() => validateEnv()).toThrow('DATABASE_URL');
  });

  it('passes in production with all required vars set', () => {
    process.env['NODE_ENV'] = 'production';
    setValidJwtSecrets();
    process.env['DATABASE_URL'] = 'postgresql://localhost/goodgo';
    process.env['CORS_ORIGINS'] = 'https://goodgo.vn';
    process.env['REDIS_HOST'] = 'redis.internal';
    process.env['FIELD_ENCRYPTION_KEY'] = 'a'.repeat(64); // 32 bytes hex

    expect(() => validateEnv()).not.toThrow();
  });
});
