export const ALPHABET_32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";

const VALUE_32: Record<string, number> = Object.fromEntries(
  Array.from(ALPHABET_32).map((ch, i) => [ch, i])
);

/**
 * Compute the Meridian v2 MOD32 check character for `payload`.
 *
 * Implements the Luhn-style MOD 32 algorithm defined in SPEC.md §7.5.
 *
 * `payload` MUST be non-empty and MUST contain only characters from `ALPHABET_32`.
 * This function is deliberately strict: it does not accept lowercase, whitespace,
 * or any visual substitutions.
 */
export function mod32CheckCharacter(payload: string): string {
  if (payload.length === 0) {
    throw new Error("payload must be non-empty");
  }
  if (!/^[\x00-\x7F]+$/.test(payload)) {
    throw new Error("payload must be ASCII");
  }

  let sum = 0;
  let factor = 2;
  for (let i = payload.length - 1; i >= 0; i--) {
    const ch = payload[i]!;
    const v = VALUE_32[ch];
    if (v === undefined) {
      throw new Error(`invalid character in payload: ${JSON.stringify(ch)}`);
    }

    const p = v * factor;
    sum += Math.floor(p / 32) + (p % 32);
    factor = factor === 2 ? 1 : 2;
  }

  const checkValue = (32 - (sum % 32)) % 32;
  const out = ALPHABET_32[checkValue];
  if (!out) {
    throw new Error("internal error: check value out of range");
  }
  return out;
}
