// Client-side mirror of server/src/invoices.ts's computeTaxAmount() — Sales
// Tax Task 3 (carried-over item A): the invoice form's totals block previews
// Subtotal / Tax / Total live as the user types, and that preview must round
// exactly the way the server will when the draft is actually saved (which in
// turn matches the DB's own recompute guard in
// db/migrations/0015_sales_tax.sql — see computeTaxAmount()'s header there
// for the scale derivation). server/src/invoices.ts remains the source of
// truth; this duplication (BigInt-only, no new dependency) follows the exact
// precedent of lineAmount.ts mirroring computeLineAmount(), and the saved
// draft's server-returned breakdown is always what detail/print render.
//
// tax = taxable subtotal * rate percent / 100, rounded HALF-UP to the nearest
// cent. Every step is BigInt integer arithmetic, never a parsed JS float
// (CLAUDE.md §2).

const DECIMAL_RE = /^\d+(\.\d+)?$/;

function toMicros(value: string): bigint {
  const [wholeRaw, fracRaw = ""] = value.split(".");
  const frac = (fracRaw + "0000").slice(0, 4);
  return BigInt(wholeRaw || "0") * 10000n + BigInt(frac || "0");
}

function fromMicros(micros: bigint): string {
  const whole = micros / 10000n;
  const frac = (micros % 10000n).toString().padStart(4, "0");
  return `${whole}.${frac}`;
}

/**
 * Computes the NUMERIC(19,4)-shaped tax preview from a taxable-subtotal
 * string (already a 4-decimal sum from lineAmount.ts's sumMoney) and a rate
 * percent string as the API returns it ("7.2500"). Returns null if either
 * input isn't a complete non-negative decimal (mirrors
 * computeLineAmountPreview's mid-keystroke convention, though in practice
 * both inputs here come from already-validated sources).
 *
 * Scales (identical to the server): taxableMicros = dollars*1e4;
 * toMicros(ratePercent) = percent*1e4; product = taxCents*1e8, so one
 * half-up division by 1e8 yields whole tax cents exactly.
 */
export function computeTaxPreview(taxableSubtotal: string, ratePercent: string): string | null {
  const taxable = taxableSubtotal.trim();
  const rate = ratePercent.trim();
  if (!DECIMAL_RE.test(taxable) || !DECIMAL_RE.test(rate)) return null;

  const taxableMicros = toMicros(taxable);
  const rateScaled = toMicros(rate); // percent * 1e4
  const DIVISOR = 100_000_000n; // 1e8
  const HALF = DIVISOR / 2n;
  const cents = (taxableMicros * rateScaled + HALF) / DIVISOR; // round-half-up
  return fromMicros(cents * 100n); // cents (1e2) back up to micros (1e4)
}
