import { cuentasAfectadas, saldoDeCuenta } from './saldo-cuenta.util';

describe('cuentasAfectadas', () => {
  it('devuelve las cuentas distintas de las cuotas', () => {
    expect(cuentasAfectadas([{ cuenta_id: 'a' }, { cuenta_id: 'b' }, { cuenta_id: 'a' }])).toEqual(['a', 'b']);
  });

  it('ignora las cuotas sin cuenta', () => {
    expect(cuentasAfectadas([{ cuenta_id: null }, { cuenta_id: 'a' }])).toEqual(['a']);
  });

  it('sin cuotas no hay cuentas', () => {
    expect(cuentasAfectadas([])).toEqual([]);
  });
});

describe('saldoDeCuenta', () => {
  it('suma los saldos pendientes de las cuotas', () => {
    const r = saldoDeCuenta([{ saldo_pendiente: 375000 }, { saldo_pendiente: 375000 }]);
    expect(r).toEqual({ saldo: 750000, estado: 'pendiente' });
  });

  it('una cuota saldada aporta cero, no su monto original', () => {
    // El bug clásico de `saldo || monto`: un 0 es falsy y cae al monto de la cuota.
    const r = saldoDeCuenta([{ saldo_pendiente: 0, dmoncuota: 375000 }, { saldo_pendiente: 375000 }]);
    expect(r.saldo).toBe(375000);
  });

  it('usa el monto de la cuota solo si no hay saldo cargado', () => {
    const r = saldoDeCuenta([{ saldo_pendiente: null, dmoncuota: 375000 }]);
    expect(r.saldo).toBe(375000);
  });

  it('todo saldado deja la cuenta en pagado', () => {
    expect(saldoDeCuenta([{ saldo_pendiente: 0 }, { saldo_pendiente: 0 }])).toEqual({ saldo: 0, estado: 'pagado' });
  });

  it('una cuenta que vuelve a deber deja de estar pagada', () => {
    // El caso del bug: el cobro cerró la cuenta y la anulación la reabre.
    expect(saldoDeCuenta([{ saldo_pendiente: 375000 }]).estado).toBe('pendiente');
  });

  it('sin cuotas el saldo es cero', () => {
    expect(saldoDeCuenta([])).toEqual({ saldo: 0, estado: 'pagado' });
  });

  it('acepta Decimal de Prisma', () => {
    const dec = (n: number) => ({ toString: () => String(n), valueOf: () => n });
    expect(saldoDeCuenta([{ saldo_pendiente: dec(1000) }]).saldo).toBe(1000);
  });
});

describe('saldoDeCuenta — estados que no aportan deuda', () => {
  it('una cuota anulada no aporta, aunque su saldo diga otra cosa', () => {
    // Pasa en la base real: la anulación de factura marca el estado pero deja
    // el saldo viejo escrito en la columna.
    const r = saldoDeCuenta([{ saldo_pendiente: 375000, estado: 'ANULADA' }, { saldo_pendiente: 375000 }]);
    expect(r.saldo).toBe(375000);
  });

  it('una cuota pagada no aporta', () => {
    const r = saldoDeCuenta([{ saldo_pendiente: 375000, estado: 'pagado' }]);
    expect(r).toEqual({ saldo: 0, estado: 'pagado' });
  });

  it('no le importa la grafía del estado', () => {
    // En la base conviven 'pendiente' y 'Pendiente'; y 'pagada'/'anulada' en femenino.
    const r = saldoDeCuenta([
      { saldo_pendiente: 100, estado: 'Pagada' },
      { saldo_pendiente: 100, estado: 'anulado' },
      { saldo_pendiente: 100, estado: 'Pendiente' },
    ]);
    expect(r.saldo).toBe(100);
  });

  it('una cuota refinanciada no aporta: su deuda vive en la cuenta nueva', () => {
    const r = saldoDeCuenta([{ saldo_pendiente: 375000, estado: 'REFINANCIADA' }]);
    expect(r.saldo).toBe(0);
  });

  it('una cuota parcial aporta su saldo', () => {
    const r = saldoDeCuenta([{ saldo_pendiente: 120000, estado: 'parcial' }]);
    expect(r).toEqual({ saldo: 120000, estado: 'pendiente' });
  });
});
