// lib/crypto.ts
import bcrypt from "bcryptjs";
import crypto from "crypto";

const SALT_ROUNDS = 12;

/**
 * Hash a plaintext password for storage. Never store plaintext passwords.
 */
export async function hashPassword(plainPassword: string): Promise<string> {
  if (!plainPassword || plainPassword.length < 8) {
    throw new Error("Password must be at least 8 characters long");
  }
  return bcrypt.hash(plainPassword, SALT_ROUNDS);
}

/**
 * Compare a plaintext password against a stored bcrypt hash.
 */
export async function verifyPassword(
  plainPassword: string,
  hash: string
): Promise<boolean> {
  if (!plainPassword || !hash) return false;
  return bcrypt.compare(plainPassword, hash);
}

/**
 * Generate a cryptographically secure random token, e.g. for domain TXT
 * verification or one-off secrets.
 */
export function generateSecureToken(bytes = 24): string {
  return crypto.randomBytes(bytes).toString("hex");
}

/**
 * Constant-time string comparison to prevent timing attacks when
 * validating HMAC signatures.
 */
export function safeCompare(a: string, b: string): boolean {
  const bufA = Buffer.from(a, "utf8");
  const bufB = Buffer.from(b, "utf8");
  if (bufA.length !== bufB.length) return false;
  return crypto.timingSafeEqual(bufA, bufB);
}
