///|
/// entropy.mbt — random bytes for PKCE verifiers and OAuth state.
///
/// `oauth_random_bytes` probes the backend entropy source (native: C
/// getentropy stub; js: crypto.getRandomValues) and falls back to a
/// time-seeded LCG only when the probe returns anything but exactly n bytes —
/// wasm/failed-probe fallback, not for credential backends.

///|
fn oauth_random_bytes(n : Int) -> Bytes {
  if n <= 0 {
    return Bytes::new(0)
  }
  let probed = oauth_random_bytes_probe(n)
  if probed.length() == n {
    probed
  } else {
    lcg_random_bytes(n)
  }
}

///|
/// OAuth state token: base64url (no padding) of 16 random bytes.
fn generate_state() -> String {
  bytes_to_base64url(oauth_random_bytes(16))
}

///|
/// Time-seeded LCG fallback for wasm and failed entropy probes.
fn lcg_random_bytes(n : Int) -> Bytes {
  let mut state = @async.now()
  let buf : Array[Byte] = []
  for _ in 0..> 33).to_int() & 0xFF).to_byte())
  }
  Bytes::from_array(buf)
}

///|
/// Wasm probe: no OS entropy source on this target; the empty result selects
/// the LCG fallback.
#cfg(not(any(target="native", target="js")))
fn oauth_random_bytes_probe(_n : Int) -> Bytes {
  Bytes::new(0)
}