/**
 * T3 — E2EEnvelope wire codec.
 *
 * RECONCILIATION: the frozen `relay-contracts` §4.4 surface ALREADY owns the envelope binary
 * layout and the deterministic per-seq nonce (`encodeEnvelope`/`decodeEnvelope`/`nonceForSeq`,
 * 14-byte header: seq(8)‖nonceLen(1)‖ciphertextLen(4)‖tagLen(1) then nonce‖ciphertext‖tag).
 * The plan's stale T3 byte layout (envVersion/aeadId) is SUPERSEDED — relay-contracts owns the
 * shape (INDEX §2.1), so P4 CONSUMES/RE-EXPORTS it and never redefines it. This module only adds
 * a boundary guard that re-throws the contract's decode error as a P4-typed `EnvelopeFormatError`
 * and enforces a hard frame-size cap (anti-overrun; the alg is carried by the key/session, not the
 * wire, so there is no unchecked wire-length allocation).
 */
import type { E2EEnvelope } from 'relay-contracts'
import {
  ContractDecodeError,
  decodeEnvelope as decodeEnvelopeRaw,
  encodeEnvelope as encodeEnvelopeRaw,
  nonceForSeq,
} from 'relay-contracts'
import { EnvelopeFormatError } from './errors.js'

/** Hard upper bound on a decoded frame (guards a decompression-bomb-style length overrun). */
export const MAX_FRAME_BYTES = 4 * 1024 * 1024

export { nonceForSeq }

/** Encode a §4.4 E2EEnvelope to its frozen wire bytes (delegates to relay-contracts). */
export function encodeEnvelope(env: E2EEnvelope): Uint8Array {
  const bytes = encodeEnvelopeRaw(env)
  if (bytes.length > MAX_FRAME_BYTES) {
    throw new EnvelopeFormatError(`encoded frame ${bytes.length} exceeds cap ${MAX_FRAME_BYTES}`)
  }
  return bytes
}

/** Decode wire bytes into a §4.4 E2EEnvelope; malformed input ⇒ typed `EnvelopeFormatError`. */
export function decodeEnvelope(buf: Uint8Array): E2EEnvelope {
  if (buf.length > MAX_FRAME_BYTES) {
    throw new EnvelopeFormatError(`frame ${buf.length} exceeds cap ${MAX_FRAME_BYTES}`)
  }
  try {
    return decodeEnvelopeRaw(buf)
  } catch (err) {
    if (err instanceof ContractDecodeError) {
      throw new EnvelopeFormatError(err.message)
    }
    throw err
  }
}
