/**
 * Zero-Knowledge Cryptography Utility
 * Uses the Web Crypto API for hardware-accelerated AES-GCM.
 */

export async function importKey(keyData: Uint8Array): Promise<CryptoKey> {
  return await self.crypto.subtle.importKey(
    "raw",
    keyData.buffer as ArrayBuffer,
    { name: "AES-GCM" },
    false,
    ["decrypt", "encrypt"]
  );
}

export async function decryptLog(
  encryptedData: Uint8Array,
  key: CryptoKey
): Promise<string> {
  // Our Go implementation sends [Nonce (12 bytes)][Ciphertext]
  const nonce = encryptedData.slice(0, 12);
  const ciphertext = encryptedData.slice(12);

  const decrypted = await self.crypto.subtle.decrypt(
    {
      name: "AES-GCM",
      iv: nonce,
    },
    key,
    ciphertext
  );

  return new TextDecoder().decode(decrypted);
}

export async function encryptData(
  plaintext: string,
  key: CryptoKey
): Promise<Uint8Array> {
  const enc = new TextEncoder();
  const data = enc.encode(plaintext);
  const nonce = self.crypto.getRandomValues(new Uint8Array(12));

  const encrypted = await self.crypto.subtle.encrypt(
    {
      name: "AES-GCM",
      iv: nonce,
    },
    key,
    data
  );

  const result = new Uint8Array(nonce.length + encrypted.byteLength);
  result.set(nonce);
  result.set(new Uint8Array(encrypted), nonce.length);
  return result;
}

export async function generateBlindIndex(
  value: string,
  key: Uint8Array
): Promise<string> {
  const enc = new TextEncoder();
  const data = enc.encode(value);
  
  const hmacKey = await self.crypto.subtle.importKey(
    "raw",
    key,
    { name: "HMAC", hash: "SHA-256" },
    false,
    ["sign"]
  );
  
  const signature = await self.crypto.subtle.sign(
    "HMAC",
    hmacKey,
    data
  );
  
  return Array.from(new Uint8Array(signature))
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
}

/**
 * Derives a 256-bit key from a password and salt using PBKDF2.
 * (Used if WebAuthn is not providing a raw key directly)
 */
export async function deriveKey(password: string, salt: string): Promise<Uint8Array> {
  const enc = new TextEncoder();
  const keyMaterial = await self.crypto.subtle.importKey(
    "raw",
    enc.encode(password),
    "PBKDF2",
    false,
    ["deriveBits", "deriveKey"]
  );

  const keyBits = await self.crypto.subtle.deriveBits(
    {
      name: "PBKDF2",
      salt: enc.encode(salt),
      iterations: 100000,
      hash: "SHA-256",
    },
    keyMaterial,
    256
  );

  return new Uint8Array(keyBits);
}
