import { imputarCobro } from './imputacion';

describe('imputarCobro', () => {
  it('sin interés pendiente todo el sobrante es vuelto', () => {
    const r = imputarCobro({ montoRecibido: 3000000, totalPagadoCapital: 2530000, interesPendiente: 0 });
    expect(r).toEqual({ capital: 2530000, interes: 0, interesRestante: 0, vuelto: 470000 });
  });

  it('el sobrante cubre el interés entero', () => {
    const r = imputarCobro({ montoRecibido: 3100000, totalPagadoCapital: 2530000, interesPendiente: 500000 });
    expect(r.interes).toBe(500000);
    expect(r.interesRestante).toBe(0);
    expect(r.vuelto).toBe(70000);
  });

  it('el sobrante cubre el interés en parte y el resto queda pendiente', () => {
    const r = imputarCobro({ montoRecibido: 2800000, totalPagadoCapital: 2530000, interesPendiente: 500000 });
    expect(r.interes).toBe(270000);
    expect(r.interesRestante).toBe(230000);
    expect(r.vuelto).toBe(0);
  });

  it('el capital consume todo: el interés queda entero pendiente', () => {
    const r = imputarCobro({ montoRecibido: 2530000, totalPagadoCapital: 2530000, interesPendiente: 500000 });
    expect(r.interes).toBe(0);
    expect(r.interesRestante).toBe(500000);
    expect(r.vuelto).toBe(0);
  });

  // Review Focus 1: el descuento puede hacer que se aplique más capital que el efectivo entregado.
  it('sobrante negativo no imputa interés ni devuelve vuelto negativo', () => {
    const r = imputarCobro({ montoRecibido: 2000000, totalPagadoCapital: 2530000, interesPendiente: 500000 });
    expect(r.interes).toBe(0);
    expect(r.interesRestante).toBe(500000);
    expect(r.vuelto).toBe(0);
  });

  // Review Focus 2: moneda con decimales — un residuo de centavos no deja el interés colgado.
  it('un residuo menor a la tolerancia da el interés por saldado', () => {
    const r = imputarCobro({ montoRecibido: 100.5, totalPagadoCapital: 50, interesPendiente: 50.504 });
    expect(r.interes).toBeCloseTo(50.5, 3);
    expect(r.interesRestante).toBe(0);
  });

  it('valores no numéricos se tratan como cero', () => {
    const r = imputarCobro({
      montoRecibido: NaN,
      totalPagadoCapital: undefined as unknown as number,
      interesPendiente: null as unknown as number,
    });
    expect(r).toEqual({ capital: 0, interes: 0, interesRestante: 0, vuelto: 0 });
  });
});

// Review Focus 4: cobro que no cubre ni la primera cuota entera.
describe('imputarCobro en un cobro parcial puro', () => {
  it('no imputa interés y no deja vuelto', () => {
    const r = imputarCobro({ montoRecibido: 1000000, totalPagadoCapital: 1000000, interesPendiente: 500000 });
    expect(r.capital).toBe(1000000);
    expect(r.interes).toBe(0);
    expect(r.interesRestante).toBe(500000);
    expect(r.vuelto).toBe(0);
  });
});
