/**
 * Password Service Unit Tests
 * TDD: Test-Driven Development
 */

import { describe, it, expect } from '@jest/globals';
import { PasswordService } from '../../../src/services/password.service';

describe('PasswordService', () => {
  describe('hash', () => {
    it('should hash password with bcrypt', async () => {
      // @ralph 这个测试是否清晰描述了期望行为？
      const plainPassword = 'MySecurePassword123!';
      const hash = await PasswordService.hash(plainPassword);

      expect(hash).toBeDefined();
      expect(hash).not.toBe(plainPassword);
      expect(hash.length).toBe(60); // bcrypt hash length
    });

    it('should generate different hashes for same password (salt)', async () => {
      // @ralph 这是否验证了salt的正确性？
      const password = 'test123';
      const hash1 = await PasswordService.hash(password);
      const hash2 = await PasswordService.hash(password);

      expect(hash1).not.toBe(hash2);
    });

    it('should handle empty string', async () => {
      // @ralph 边界条件是否考虑充分？
      const hash = await PasswordService.hash('');
      expect(hash).toBeDefined();
      expect(hash.length).toBe(60);
    });

    it('should handle special characters', async () => {
      // @ralph 特殊字符是否正确处理？
      const password = '!@#$%^&*()_+-=[]{}|;:\'",.<>?/~`';
      const hash = await PasswordService.hash(password);
      expect(hash).toBeDefined();
    });

    it('should handle very long passwords', async () => {
      // @ralph 是否考虑了长度限制？
      const password = 'a'.repeat(1000);
      const hash = await PasswordService.hash(password);
      expect(hash).toBeDefined();
    });
  });

  describe('verify', () => {
    it('should verify correct password', async () => {
      // @ralph 基本功能是否正确？
      const password = 'test123';
      const hash = await PasswordService.hash(password);
      const isValid = await PasswordService.verify(password, hash);

      expect(isValid).toBe(true);
    });

    it('should reject wrong password', async () => {
      // @ralph 错误密码是否被正确拒绝？
      const hash = await PasswordService.hash('test123');
      const isValid = await PasswordService.verify('wrong', hash);

      expect(isValid).toBe(false);
    });

    it('should be case sensitive', async () => {
      // @ralph 大小写敏感性是否正确？
      const hash = await PasswordService.hash('Password123');
      const isValid = await PasswordService.verify('password123', hash);

      expect(isValid).toBe(false);
    });

    it('should reject invalid hash format', async () => {
      // @ralph 错误处理是否完善？
      await expect(
        PasswordService.verify('test', 'invalid-hash')
      ).rejects.toThrow();
    });

    it('should reject empty hash', async () => {
      // @ralph 空值处理是否正确？
      await expect(
        PasswordService.verify('test', '')
      ).rejects.toThrow();
    });

    it('should handle unicode characters', async () => {
      // @ralph Unicode是否正确处理？
      const password = '密码123🔐';
      const hash = await PasswordService.hash(password);
      const isValid = await PasswordService.verify(password, hash);

      expect(isValid).toBe(true);
    });
  });

  describe('strength validation', () => {
    it('should validate strong password', () => {
      // @ralph 强度规则是否合理？
      const strong = PasswordService.checkStrength('Str0ng!Pass');
      expect(strong.isStrong).toBe(true);
    });

    it('should reject weak password (too short)', () => {
      // @ralph 弱密码是否被正确识别？
      const weak = PasswordService.checkStrength('12345');
      expect(weak.isStrong).toBe(false);
      expect(weak.reason).toContain('长度');
    });

    it('should reject weak password (no numbers)', () => {
      // @ralph 规则是否全面？
      const weak = PasswordService.checkStrength('abcdefgh');
      expect(weak.isStrong).toBe(false);
    });
  });
});
