export const HashAlgorithms = ["SHA-1", "SHA-256", "SHA-384", "SHA-512"] as const;
export type HashAlgorithm = (typeof HashAlgorithms)[number];
export async function digest(alg: HashAlgorithm, input: string, salt?: string, pepper?: string) {
   if (!HashAlgorithms.includes(alg)) {
      throw new Error(`Invalid hash algorithm: ${alg}`);
   }

   // convert to Uint8Array
   const data = new TextEncoder().encode((salt ?? "") + input + (pepper ?? ""));

   // hash to alg
   const hashBuffer = await crypto.subtle.digest(alg, data);

   // convert hash to hex string
   const hashArray = Array.from(new Uint8Array(hashBuffer));
   return hashArray.map((byte) => byte.toString(16).padStart(2, "0")).join("");
}

export const hash = {
   sha256: async (input: string, salt?: string, pepper?: string) =>
      digest("SHA-256", input, salt, pepper),
   sha1: async (input: string, salt?: string, pepper?: string) =>
      digest("SHA-1", input, salt, pepper),
};

export async function checksum(s: any) {
   const o = typeof s === "string" ? s : JSON.stringify(s);
   return await digest("SHA-1", o);
}

export function secureRandomString(length: number): string {
   const array = new Uint8Array(length);
   crypto.getRandomValues(array);
   return Array.from(array, (byte) => String.fromCharCode(33 + (byte % 94))).join("");
}
