/**
 * Money helpers — IRR Rials, integer, no floats (see
 * `dev/contracts/conventions/money-and-types.md`).
 *
 * Money crosses the wire as a string of digits (Rials) because IRR aggregates exceed
 * JS's safe-integer range. We parse with BigInt and format for display. Toman is
 * display-only (1 Toman = 10 Rials) and is derived here, never stored or sent.
 */

import { localeTag } from './number';

const RIALS_PER_TOMAN = BigInt(10);
const INTEGER_STRING = /^-?\d+$/;

/** Parses an IRR value (digit string, number, or bigint) into an integer-safe bigint. */
export function parseIrr(value: string | number | bigint): bigint {
  if (typeof value === 'bigint') return value;
  if (typeof value === 'number') {
    if (!Number.isInteger(value)) throw new Error(`IRR must be an integer, got ${value}`);
    return BigInt(value);
  }
  const trimmed = value.trim();
  if (!INTEGER_STRING.test(trimmed)) throw new Error(`Invalid IRR integer string: "${value}"`);
  return BigInt(trimmed);
}

/** Converts Rials to Toman (integer division — IRR are whole Rials). */
export function rialToToman(value: string | number | bigint): bigint {
  return parseIrr(value) / RIALS_PER_TOMAN;
}

/**
 * Converts a whole-Toman amount (what the nurse types in the price field) to the IRR Rial
 * digit-string the wire expects (×10). This is the sanctioned Toman→Rial conversion at the
 * *field boundary* (money-and-types.md): the UI collects Toman, the contract carries Rials.
 * Integer-safe (BigInt); never a float on the price path.
 */
export function tomanToRial(value: string | number | bigint): string {
  return String(parseIrr(value) * RIALS_PER_TOMAN);
}

/**
 * Multiplies an IRR Rial amount by an integer count, returning the IRR digit-string. Used for
 * the builder's unit-aware estimated total (`price` × `session_count`) — a total is only ever
 * `price` interpreted by its `price_unit` and multiplied by the count, never `price` alone.
 */
export function multiplyIrr(value: string | number | bigint, count: number): string {
  if (!Number.isInteger(count) || count < 0) throw new Error(`count must be a non-negative integer, got ${count}`);
  return String(parseIrr(value) * BigInt(count));
}

/** Formats a grouped Rial amount (no unit). `fa` uses Persian digits. */
export function formatIrr(value: string | number | bigint, locale: string = 'fa'): string {
  return new Intl.NumberFormat(localeTag(locale)).format(parseIrr(value));
}

/**
 * Formats an IRR amount as a grouped Toman number for display (no unit — pair it with
 * the `common.currency_toman` label). `fa` renders Persian digits.
 */
export function formatIrrToToman(value: string | number | bigint, locale: string = 'fa'): string {
  return new Intl.NumberFormat(localeTag(locale)).format(rialToToman(value));
}
