// Shared helpers for the 6-digit email codes used by sign-up verification and
// password reset. Both flows store a salted hash keyed by email, so the code
// itself only ever lives in the outgoing mail.

import { createHash, randomInt, timingSafeEqual } from "crypto";

export const CODE_TTL_MINUTES = 15;

// A 6-digit code is only 1,000,000 wide, so the attempt cap is what actually
// makes it safe to email. Both code tables carry an `attempts` column.
export const MAX_CODE_ATTEMPTS = 5;

export const generateCode = (): string =>
  String(randomInt(0, 1_000_000)).padStart(6, "0");

export const hashCode = (email: string, code: string): string =>
  createHash("sha256").update(`${email}:${code}`).digest("hex");

export const codeMatches = (
  storedHash: string,
  email: string,
  code: string,
): boolean => {
  const expected = Buffer.from(storedHash, "hex");
  const actual = Buffer.from(hashCode(email, code), "hex");

  return expected.length === actual.length && timingSafeEqual(expected, actual);
};

// Gmail and iOS Mail only offer a one-tap "copy code" / keyboard suggestion
// when the code leads the subject line and the body opens with a recognised
// phrasing. Keep both formats intact when editing this copy.
export const verificationEmail = (code: string) => ({
  subject: `${code} is your Waseel verification code`,
  text:
    `${code} is your Waseel verification code.\n\n` +
    `Welcome to Waseel! Enter this code in the app to finish signing up.\n` +
    `It expires in ${CODE_TTL_MINUTES} minutes.\n`,
});

export const resetEmail = (code: string) => ({
  subject: `${code} is your Waseel password reset code`,
  text:
    `${code} is your Waseel password reset code.\n\n` +
    `We received a request to reset your Waseel password. Enter this code in ` +
    `the app to choose a new one.\n` +
    `It expires in ${CODE_TTL_MINUTES} minutes. If you didn't ask for this, ` +
    `you can ignore this email.\n`,
});
