import { calcularTotales, subtotalItem } from './totales.util';

const unico = (cantidad: number, precio: number, desc = 0) => ({
  cantidad, precio_unitario: precio, descuento_pct: desc, tipo_cobro: 'unico',
});
const recurrente = (precio: number, frecuencia: string, n_meses?: number) => ({
  cantidad: 1, precio_unitario: precio, tipo_cobro: 'recurrente', frecuencia, n_meses,
});

describe('subtotalItem', () => {
  it('multiplica cantidad por precio', () => {
    expect(subtotalItem(unico(10, 50_000))).toBe(500_000);
  });

  it('aplica el descuento en porcentaje', () => {
    expect(subtotalItem(unico(10, 50_000, 10))).toBe(450_000);
  });

  it('recorta un descuento fuera de rango en vez de dar un total negativo', () => {
    expect(subtotalItem(unico(1, 1000, 150))).toBe(0);
    expect(subtotalItem(unico(1, 1000, -50))).toBe(1000);
  });
});

describe('calcularTotales', () => {
  it('lo único suma al valor único y no al MRR', () => {
    const t = calcularTotales([unico(2, 100_000), unico(1, 50_000)]);
    expect(t.valor_unico).toBe(250_000);
    expect(t.valor_mrr).toBe(0);
    expect(t.valor_tcv).toBe(250_000);
  });

  /**
   * El corazón del cálculo: un abono trimestral de 300.000 aporta 100.000 de
   * MRR, no 300.000. Sin normalizar, el forecast mezcla plazos distintos y da un
   * número que no significa nada.
   */
  it('normaliza el recurrente a ingreso mensual equivalente', () => {
    expect(calcularTotales([recurrente(300_000, 'trimestral')]).valor_mrr).toBe(100_000);
    expect(calcularTotales([recurrente(1_200_000, 'anual')]).valor_mrr).toBe(100_000);
    expect(calcularTotales([recurrente(100_000, 'mensual')]).valor_mrr).toBe(100_000);
    expect(calcularTotales([recurrente(600_000, 'semestral')]).valor_mrr).toBe(100_000);
  });

  it('con "cada_n_meses" usa n_meses como período', () => {
    expect(calcularTotales([recurrente(400_000, 'cada_n_meses', 4)]).valor_mrr).toBe(100_000);
  });

  it('el TCV proyecta 12 meses cuando el ítem no fija vigencia', () => {
    const t = calcularTotales([recurrente(100_000, 'mensual')]);
    expect(t.valor_tcv).toBe(1_200_000);
  });

  it('el TCV respeta la vigencia declarada', () => {
    const t = calcularTotales([recurrente(100_000, 'mensual', 6)]);
    expect(t.valor_mrr).toBe(100_000);
    expect(t.valor_tcv).toBe(600_000);
  });

  it('venta mixta: alta única más abono mensual (ejemplo B de la spec §7.3)', () => {
    const t = calcularTotales([unico(1, 2_500_000), recurrente(350_000, 'mensual', 12)]);
    expect(t.valor_unico).toBe(2_500_000);
    expect(t.valor_mrr).toBe(350_000);
    expect(t.valor_tcv).toBe(6_700_000);
  });

  it('sin ítems da todo en cero, no NaN', () => {
    expect(calcularTotales([])).toEqual({ valor_unico: 0, valor_mrr: 0, valor_tcv: 0 });
  });
});
