/**
 * The premium arithmetic the Access capture form did in unbound calculated
 * controls, moved somewhere it can be tested.
 *
 * Two figures are derived, everything else is keyed by hand:
 *
 *   base  = netPremium + surcharge + policyFee
 *   tax   = round(base * rate)
 *   total = base + tax
 *
 * The surcharge IS part of the taxable base. That is not an assumption — it is
 * the only reading that reconciles the books. Policy 7006785 (MULT, semestral,
 * two payments) prints IVA 52.03 and 47.84 against net premiums 610.86 / 589.71,
 * surcharges 8.55 / 8.26 and policy fees 31.00 / 0.00; excluding the surcharge
 * gives 51.35, which matches nothing on the page.
 *
 * The surcharge itself is NEVER derived. It is the carrier's financing charge
 * for paying in installments, quoted per policy, so staff key it in. It only
 * ever appears on a policy that is not paid annually or in a single exhibición
 * — `surchargeApplies` is what the UI uses to grey the field out.
 */

/** Used when neither the policy nor its type carries a rate. Matches the
 *  single row both legacy IMPUESTOS tables held (0.08 = 8%). */
export const DEFAULT_TAX_RATE = 0.08;

export type PaymentFrequencyValue =
  | "ANNUAL"
  | "SEMIANNUAL"
  | "QUARTERLY"
  | "MONTHLY"
  | "SINGLE";

/** Paying in more than one exhibición is what earns a surcharge. A null
 *  frequency (every migrated row — Access's FORMA PAGO was dropped by the
 *  original ETL) is treated as "unknown, allow it" rather than "annual":
 *  refusing to show a figure that is sitting in the legacy data would hide it. */
export function surchargeApplies(
  frequency: PaymentFrequencyValue | null | undefined,
): boolean {
  return frequency !== "ANNUAL" && frequency !== "SINGLE";
}

function num(v: unknown): number {
  if (v === null || v === undefined || v === "") return 0;
  const n = typeof v === "number" ? v : Number(v);
  return Number.isFinite(n) ? n : 0;
}

/** Half-up to cents, the way the printed policy rounds. */
export function round2(n: number): number {
  return Math.round((n + Number.EPSILON) * 100) / 100;
}

export interface PremiumParts {
  netPremium?: unknown;
  surcharge?: unknown;
  policyFee?: unknown;
}

export function taxableBase(p: PremiumParts): number {
  return round2(num(p.netPremium) + num(p.surcharge) + num(p.policyFee));
}

export function computeTax(p: PremiumParts, rate: number): number {
  return round2(taxableBase(p) * rate);
}

export function computeTotal(p: PremiumParts, rate: number): number {
  return round2(taxableBase(p) + computeTax(p, rate));
}

/** Rate ladder: the figure stored on the policy (so an old policy keeps the
 *  rate it was issued at even after the catalog changes), else the rate on its
 *  line of business, else the shipped default. */
export function resolveTaxRate(
  policyRate: unknown,
  policyTypeRate: unknown,
): number {
  for (const candidate of [policyRate, policyTypeRate]) {
    if (candidate === null || candidate === undefined || candidate === "") continue;
    const n = Number(candidate);
    if (Number.isFinite(n) && n >= 0) return n;
  }
  return DEFAULT_TAX_RATE;
}
