/**
 * Ed25519 primitives over WebCrypto (`globalThis.crypto.subtle`) — no native binary, no external
 * dependency. Keys are `CryptoKey` (matching the plan's frozen signatures). Node 18.4+ / all
 * browsers expose Ed25519 in SubtleCrypto.
 */
const subtle = globalThis.crypto.subtle

const ED25519 = { name: 'Ed25519' } as const

/** Coerce to an ArrayBuffer-backed view (WebCrypto's `BufferSource` requires `Uint8Array<ArrayBuffer>`). */
function ab(u: Uint8Array): Uint8Array<ArrayBuffer> {
  const out = new Uint8Array(u.byteLength)
  out.set(u)
  return out
}

/** Local key-pair shape (avoids the DOM-only `CryptoKeyPair` global name under the Node lib set). */
export interface Ed25519KeyPair {
  readonly publicKey: CryptoKey
  readonly privateKey: CryptoKey
}

export async function generateEd25519KeyPair(): Promise<Ed25519KeyPair> {
  return (await subtle.generateKey(ED25519, true, ['sign', 'verify'])) as Ed25519KeyPair
}

export async function signEd25519(privateKey: CryptoKey, data: Uint8Array): Promise<Uint8Array> {
  const sig = await subtle.sign(ED25519, privateKey, ab(data))
  return new Uint8Array(sig)
}

export async function verifyEd25519(
  publicKey: CryptoKey,
  signature: Uint8Array,
  data: Uint8Array,
): Promise<boolean> {
  return subtle.verify(ED25519, publicKey, ab(signature), ab(data))
}

export async function importEd25519PublicRaw(raw: Uint8Array): Promise<CryptoKey> {
  return subtle.importKey('raw', ab(raw), ED25519, true, ['verify'])
}

export async function exportEd25519PublicRaw(publicKey: CryptoKey): Promise<Uint8Array> {
  return new Uint8Array(await subtle.exportKey('raw', publicKey))
}

export async function sha256(data: Uint8Array): Promise<Uint8Array> {
  return new Uint8Array(await subtle.digest('SHA-256', ab(data)))
}
