import { randomBytes } from "node:crypto";

import { hashToken, verifyTokenHash } from "./tokens";

const RECOVERY_CODE_SEGMENT_LENGTH = 4;

function formatRecoveryCode(bytes: Buffer): string {
  const hex = bytes.toString("hex").toUpperCase();
  return `${hex.slice(0, RECOVERY_CODE_SEGMENT_LENGTH)}-${hex.slice(RECOVERY_CODE_SEGMENT_LENGTH)}`;
}

export function generateRecoveryCodes(count = 10): string[] {
  return Array.from({ length: count }, () =>
    formatRecoveryCode(randomBytes(RECOVERY_CODE_SEGMENT_LENGTH)),
  );
}

export function hashRecoveryCode(code: string): string {
  return hashToken(normalizeRecoveryCode(code));
}

export function verifyRecoveryCode(code: string, hashed: string): boolean {
  return verifyTokenHash(normalizeRecoveryCode(code), hashed);
}

function normalizeRecoveryCode(code: string): string {
  return code.trim().toUpperCase().replace(/\s+/g, "");
}
