/**
 * AES-GCM 封装，密文格式: base64( iv(12) | ciphertext+tag )
 */

function b64encode(bytes: Uint8Array): string {
  let bin = '';
  for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]!);
  return btoa(bin);
}

function b64decode(b64: string): Uint8Array {
  const bin = atob(b64);
  const out = new Uint8Array(bin.length);
  for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i)!;
  return out;
}

async function importAesKey(masterKeyB64: string): Promise<CryptoKey> {
  const raw = b64decode(masterKeyB64.trim());
  if (raw.length !== 32) {
    throw new Error('MASTER_KEY 必须为 32 字节的 base64 编码');
  }
  return crypto.subtle.importKey(
    'raw',
    raw as BufferSource,
    { name: 'AES-GCM' },
    false,
    ['encrypt', 'decrypt'],
  );
}

export async function encryptSecret(
  masterKeyB64: string,
  plaintextUtf8: string,
): Promise<string> {
  const key = await importAesKey(masterKeyB64);
  const iv = crypto.getRandomValues(new Uint8Array(12));
  const enc = new TextEncoder();
  const cipher = await crypto.subtle.encrypt(
    { name: 'AES-GCM', iv },
    key,
    enc.encode(plaintextUtf8),
  );
  const combined = new Uint8Array(iv.length + cipher.byteLength);
  combined.set(iv, 0);
  combined.set(new Uint8Array(cipher), iv.length);
  return b64encode(combined);
}

export async function decryptSecret(
  masterKeyB64: string,
  storedB64: string,
): Promise<string> {
  const key = await importAesKey(masterKeyB64);
  const combined = b64decode(storedB64);
  if (combined.length < 12 + 16) throw new Error('密文损坏');
  const iv = combined.slice(0, 12);
  const data = combined.slice(12);
  const plain = await crypto.subtle.decrypt(
    { name: 'AES-GCM', iv },
    key,
    data,
  );
  return new TextDecoder().decode(plain);
}
