import { ValueObject } from "@repo/rdx-ddd";
import { Result } from "@repo/rdx-utils";
import bcrypt from "bcrypt";
import * as z from "zod/v4";

interface HashPasswordProps {
  value: string;
}

export class HashPassword extends ValueObject<HashPasswordProps> {
  private static readonly SALT_ROUNDS = 10;

  static createFromPlainText(plainTextPassword: string): Result<HashPassword, Error> {
    const result = HashPassword.validate(plainTextPassword);

    if (!result.success) {
      return Result.fail(new Error(result.error.errors[0].message));
    }

    const hashed = bcrypt.hashSync(result.data, this.SALT_ROUNDS);
    return Result.ok(new HashPassword({ value: hashed }));
  }

  private static validate(password: string) {
    const schema = z.string().min(6, { message: "Password must be at least 6 characters long" });
    return schema.safeParse(password);
  }

  static createFromHash(hashedPassword: string): Result<HashPassword, Error> {
    return Result.ok(new HashPassword({ value: hashedPassword }));
  }

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

  getValue() {
    return this.props.value;
  }

  toString() {
    return this.props.value;
  }

  toPrimitive() {
    return this.props.value;
  }
}
