/**
 * Password Service
 * Handles password hashing and verification using bcrypt
 */

import bcrypt from 'bcrypt';

export interface StrengthResult {
  isStrong: boolean;
  reason?: string;
}

export class PasswordService {
  private static readonly SALT_ROUNDS = 10;

  /**
   * Hash a plain text password using bcrypt
   * @param password - Plain text password
   * @returns Promise<string> - Hashed password
   */
  static async hash(password: string): Promise<string> {
    return bcrypt.hash(password, this.SALT_ROUNDS);
  }

  /**
   * Verify a plain text password against a hash
   * @param password - Plain text password
   * @param hash - Hashed password
   * @returns Promise<boolean> - True if password matches
   * @throws Error if hash format is invalid
   */
  static async verify(password: string, hash: string): Promise<boolean> {
    // Validate hash format (bcrypt hashes are 60 chars and start with $2a$, $2b$, or $2y$)
    if (!hash || typeof hash !== 'string') {
      throw new Error('Invalid hash format');
    }

    const bcryptHashRegex = /^\$2[aby]\$[\d]+\$./;
    if (!bcryptHashRegex.test(hash)) {
      throw new Error('Invalid hash format');
    }

    return bcrypt.compare(password, hash);
  }

  /**
   * Check password strength
   * @param password - Plain text password
   * @returns StrengthResult - Strength check result
   */
  static checkStrength(password: string): StrengthResult {
    if (password.length < 8) {
      return { isStrong: false, reason: '密码长度至少8个字符' };
    }

    if (!/[A-Z]/.test(password)) {
      return { isStrong: false, reason: '密码需要包含大写字母' };
    }

    if (!/[a-z]/.test(password)) {
      return { isStrong: false, reason: '密码需要包含小写字母' };
    }

    if (!/[0-9]/.test(password)) {
      return { isStrong: false, reason: '密码需要包含数字' };
    }

    if (!/[!@#$%^&*()_+\-=\[\]{}|;:,.<>?]/.test(password)) {
      return { isStrong: false, reason: '密码需要包含特殊字符' };
    }

    return { isStrong: true };
  }
}
