/**
 * @module utils/collation
 * @description Deterministic string ordering for persisted indexes and any comparison
 * that must agree with the native (Rust) column store / aggregation engine.
 *
 * Strings are compared by **UTF-8 byte order**, which equals Unicode code-point order
 * and is byte-for-byte identical to Rust's `str::cmp` (`as_bytes().cmp()`). This is:
 * - **deterministic** across environments (unlike `localeCompare`, whose default-locale
 *   ordering varies by OS / Node / ICU build — unsafe for a persisted sorted index), and
 * - **cross-language consistent** with `@soulcraft/cor`'s native column store and
 *   aggregation sort, so query results are identical with or without the native plugin.
 *
 * Use this instead of `String.localeCompare` and the `<`/`>` operators (which compare
 * UTF-16 code units and diverge from code-point order for supplementary-plane characters)
 * wherever ordering is persisted or must match the native engine. See cor `docs/ADR-001`.
 */

const utf8 = new TextEncoder()

/**
 * Compare two strings by UTF-8 byte order (== Unicode code-point order == Rust `str::cmp`).
 *
 * @param a - First string.
 * @param b - Second string.
 * @returns Negative if `a < b`, positive if `a > b`, `0` if equal — by UTF-8 byte order.
 * @example
 * ['b', 'A', 'a'].sort(compareCodePoints) // ['A', 'a', 'b']  (byte order: A=65, a=97, b=98)
 */
export function compareCodePoints(a: string, b: string): number {
  const ea = utf8.encode(a)
  const eb = utf8.encode(b)
  const len = ea.length < eb.length ? ea.length : eb.length
  for (let i = 0; i < len; i++) {
    if (ea[i] !== eb[i]) return ea[i] - eb[i]
  }
  return ea.length - eb.length
}
