import * as bcrypt from 'bcryptjs';

/**
 * Password utility functions for secure password handling
 *
 * This module provides functions for securely hashing and comparing passwords
 * using the bcrypt algorithm. Bcrypt is specifically designed for password
 * hashing with built-in salting and adjustable work factor.
 *
 * Security features:
 * - Salt generation (automatic, unique per hash)
 * - Adaptive work factor (configurable cost)
 * - Timing attack resistance
 * - Widely audited and battle-tested
 *
 * @see https://en.wikipedia.org/wiki/Bcrypt
 * @see https://www.npmjs.com/package/bcryptjs
 *
 * @example
 * // Hash a password during user registration
 * const hashedPassword = await encryptPassword('userPassword123');
 * // Store hashedPassword in database
 *
 * @example
 * // Verify password during login
 * const isValid = await comparePassword('userPassword123', storedHash);
 * if (isValid) {
 *   // Grant access
 * }
 */

/**
 * Encrypts (hashes) a password using bcrypt
 *
 * Generates a secure hash of the password with a randomly generated salt
 * and the specified work factor. The returned hash includes:
 * - Algorithm identifier
 * - Work factor
 * - Salt
 * - Hashed password
 *
 * @param password - Plain text password to hash
 * @returns Promise resolving to the bcrypt hash string
 *
 * @throws Error if hashing fails (invalid input, memory issues, etc.)
 *
 * @note Work factor of 10 means 2^10 = 1024 iterations
 * @note Higher work factor = more secure but slower (10 is good default)
 * @note Never store raw passwords - always hash before storage
 *
 * @example
 * // Returns something like: '$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy'
 * const hash = await encryptPassword('mySecurePassword');
 */
export const encryptPassword = async (password: string): Promise<string> => {
  // Work factor (cost) determines hashing complexity
  // Higher cost = more secure but slower (10 is a good balance)
  const saltRounds = 10;

  return bcrypt.hash(password, saltRounds);
};

/**
 * Compares a plain text password against a bcrypt hash
 *
 * Securely compares a candidate password with a stored hash.
 * Uses constant-time comparison to prevent timing attacks.
 *
 * @param password - Plain text password to verify
 * @param hash - Bcrypt hash to compare against (from database)
 * @returns Promise resolving to true if password matches, false otherwise
 *
 * @throws Error if comparison fails (invalid hash format, etc.)
 *
 * @note Uses constant-time comparison to prevent timing attacks
 * @note Returns false (not throws) for invalid passwords
 * @note Hash must be a valid bcrypt hash (from encryptPassword)
 *
 * @example
 * // Check if provided password matches stored hash
 * const isMatch = await comparePassword('userInput', storedHash);
 * if (isMatch) {
 *   // Authentication successful
 * }
 */
export const comparePassword = async (
  password: string,
  hash: string,
): Promise<boolean> => {
  return bcrypt.compare(password, hash);
};
