/**
 * Imputación de un cobro: primero capital, después interés manual.
 *
 * El capital ya se repartió entre las cuotas (más vieja primero) antes de
 * llegar acá. Lo que el capital no consumió del monto entregado es lo que
 * puede pagar interés; lo que sobra después de eso es el vuelto del cliente.
 *
 * La mora por tasa NO pasa por acá: se calcula aparte y se suma encima de lo
 * que el cliente entregó.
 */

/** Residuo por debajo del cual un interés se da por saldado (monedas con decimales). */
const TOLERANCIA_SALDADO = 0.009;

const num = (v: unknown): number => {
  const n = Number(v);
  return Number.isFinite(n) ? n : 0;
};

export interface ImputacionParams {
  /** Lo que el cliente entrega en este cobro. */
  montoRecibido: number;
  /** Capital efectivamente pagado en efectivo, ya neto de descuento. */
  totalPagadoCapital: number;
  /** Interés manual pendiente: el de las cuotas del cobro más el de sus cuentas. */
  interesPendiente: number;
}

export interface ImputacionResultado {
  /** Capital imputado. Es el que ya venía repartido; se devuelve para que el resumen no lo recalcule. */
  capital: number;
  /** Interés que este cobro le saca al monto entregado. */
  interes: number;
  /** Interés que queda pendiente para el próximo cobro. */
  interesRestante: number;
  /** Vuelto real del cliente, ya descontado el interés. */
  vuelto: number;
}

export function imputarCobro(params: ImputacionParams): ImputacionResultado {
  const montoRecibido = Math.max(0, num(params.montoRecibido));
  const capital = Math.max(0, num(params.totalPagadoCapital));
  const pendiente = Math.max(0, num(params.interesPendiente));

  // Lo que el capital no consumió. Con descuento se puede aplicar más capital
  // que el efectivo entregado, así que el sobrante puede dar negativo.
  const sobrante = Math.max(0, montoRecibido - capital);

  const interes = Math.min(sobrante, pendiente);
  const restanteBruto = pendiente - interes;

  return {
    capital,
    interes,
    interesRestante: restanteBruto > TOLERANCIA_SALDADO ? restanteBruto : 0,
    vuelto: Math.max(0, sobrante - interes),
  };
}
