/**
 * A UUID v4, in a browser that may not be in a secure context.
 *
 * ── Why this exists ──
 *
 * `crypto.randomUUID()` is SECURE-CONTEXT ONLY. Over plain http on anything that
 * is not localhost it is not defined at all, and calling it throws
 * `TypeError: crypto.randomUUID is not a function`.
 *
 * Officer is reached over the tailnet — `http://officer-dev:9000` — which is
 * neither localhost nor https, so every one of these threw. Worst inside a
 * `useState` initialiser, where the throw happens during render and takes the
 * whole tree down: chat crashed at the end of every turn, on the assistant
 * message that did not have an id yet.
 *
 * `crypto.getRandomValues()` carries NO such restriction — it is on `Crypto`,
 * not on `SubtleCrypto`, and works in an insecure context. So the randomness
 * below is exactly what `randomUUID` would have given; only the convenience
 * wrapper was missing.
 *
 * ── This is not a weakening ──
 *
 * Same CSPRNG, same 122 bits of entropy, same version and variant bits. When
 * `randomUUID` exists it is used unchanged; otherwise the value is assembled by
 * hand from the source `randomUUID` itself draws on.
 *
 * The final fallback is `Math.random`, and it is there for completeness rather
 * than for use: a browser with no `crypto` object at all cannot run this app.
 * Never reached in practice, and marked so nobody mistakes it for a supported
 * path or copies it somewhere it would matter.
 */
export function randomId(): string {
  const c = globalThis.crypto;

  if (typeof c?.randomUUID === 'function') return c.randomUUID();

  if (typeof c?.getRandomValues === 'function') {
    const bytes = c.getRandomValues(new Uint8Array(16));
    // Version 4, and the RFC 4122 variant. Exactly what randomUUID sets.
    bytes[6] = (bytes[6]! & 0x0f) | 0x40;
    bytes[8] = (bytes[8]! & 0x3f) | 0x80;
    const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');
    return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
  }

  // Unreachable in any browser that can run this app. Not a supported path.
  return `${Date.now().toString(16)}-${Math.random().toString(16).slice(2, 10)}`;
}
