import * as bcrypt from 'bcrypt';
import { Result, ValueObject } from '@modules/shared';

interface HashedPasswordProps {
  value: string;
}

export class HashedPassword extends ValueObject<HashedPasswordProps> {
  private static readonly SALT_ROUNDS = parseInt(
    process.env['BCRYPT_ROUNDS'] ?? '12',
    10,
  );
  private static readonly MIN_LENGTH = 8;

  get value(): string {
    return this.props.value;
  }

  static async fromPlain(password: string): Promise<Result<HashedPassword, string>> {
    if (password.length < this.MIN_LENGTH) {
      return Result.err(`Mật khẩu phải có ít nhất ${this.MIN_LENGTH} ký tự`);
    }
    const hash = await bcrypt.hash(password, this.SALT_ROUNDS);
    return Result.ok(new HashedPassword({ value: hash }));
  }

  static fromHash(hash: string): HashedPassword {
    return new HashedPassword({ value: hash });
  }

  async compare(plainPassword: string): Promise<boolean> {
    return bcrypt.compare(plainPassword, this.props.value);
  }
}
