import { runtimeEnv } from "./db";

function bytesToBase64(bytes: Uint8Array) {
  let binary = "";
  for (const byte of bytes) binary += String.fromCharCode(byte);
  return btoa(binary);
}

function base64ToBytes(value: string) {
  const binary = atob(value);
  return Uint8Array.from(binary, (character) => character.charCodeAt(0));
}

async function encryptionKey() {
  const secret = runtimeEnv().TOKEN_ENCRYPTION_KEY;
  if (!secret || secret.length < 24) throw new Error("TOKEN_ENCRYPTION_KEY 설정이 필요합니다.");
  const digest = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(secret));
  return crypto.subtle.importKey("raw", digest, "AES-GCM", false, ["encrypt", "decrypt"]);
}

export async function encryptToken(token: string) {
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const encrypted = await crypto.subtle.encrypt({ name: "AES-GCM", iv }, await encryptionKey(), new TextEncoder().encode(token));
  return { tokenEncrypted: bytesToBase64(new Uint8Array(encrypted)), tokenIv: bytesToBase64(iv) };
}

export async function decryptToken(tokenEncrypted: string, tokenIv: string) {
  const decrypted = await crypto.subtle.decrypt(
    { name: "AES-GCM", iv: base64ToBytes(tokenIv) },
    await encryptionKey(),
    base64ToBytes(tokenEncrypted),
  );
  return new TextDecoder().decode(decrypted);
}
