import { armarResumen, PresupuestoResumen, ProductoInfo } from './presupuestos-resumen';

/** Resumen de presupuestos de un vendedor (pedido DOBA, oct-2026). */
const item = (over: any) => ({ tipo: 'PRODUCTO', unidad_medida: 'UNI', ...over });
const pres = (numero: string, cliente: string, items: any[], moneda = 'PYG'): PresupuestoResumen => ({
  id: numero, numero, fecha: '2026-10-21', estado: 'DRAFT', moneda,
  cliente: { id: `cli-${cliente}`, nombre: cliente, documento: '800' }, vendedor: 'Cristian Olmedo', items,
});
const productos = new Map<string, ProductoInfo>([
  ['choclo', { id: 'choclo', codigo: 'CH1', descripcion: 'CHOCLO NUAR 380g', costo: 3085, empaque: { nombre: 'Caja', factor: 24 } }],
  ['sardina', { id: 'sardina', codigo: 'SA1', descripcion: 'SARDINA NUAR', costo: 3113, empaque: null }],
]);

describe('armarResumen', () => {
  const presupuestos = [
    pres('P-1', 'COMERCIAL A', [
      item({ producto_id: 'choclo', descripcion: 'choclo', cantidad: 120, precio_unitario: 3700, total: 444000 }),
      item({ tipo: 'SUBTITULO', producto_id: null, descripcion: 'Enlatados', cantidad: 0, precio_unitario: 0, total: 0 }),
    ]),
    pres('P-2', 'COMERCIAL B', [
      item({ producto_id: 'choclo', descripcion: 'choclo', cantidad: 48, precio_unitario: 3800, total: 182400 }),
      item({ producto_id: 'sardina', descripcion: 'sardina', cantidad: 60, precio_unitario: 4700, total: 282000 }),
    ]),
  ];

  it('por producto: cantidad, cajas, monto y precio promedio', () => {
    const r = armarResumen(presupuestos, productos, { verCosto: false });
    const choclo = r.por_producto.find((p) => p.producto_id === 'choclo')!;
    expect(choclo).toMatchObject({ cantidad: 168, empaques: 7, monto: 626400, precio_promedio: 3728.57, clientes: 2 });
    expect(choclo.empaque).toEqual({ nombre: 'Caja', factor: 24 });
    expect(r.por_producto.find((p) => p.producto_id === 'sardina')).toMatchObject({ cantidad: 60, empaques: null });
  });

  it('sin permiso no expone costo ni margen', () => {
    const r = armarResumen(presupuestos, productos, { verCosto: false });
    expect(r.por_producto[0]).not.toHaveProperty('costo_unitario');
    expect(r.por_producto[0]).not.toHaveProperty('margen_pct');
    expect(r.ver_costo).toBe(false);
  });

  it('con permiso calcula costo y margen sobre el precio de venta', () => {
    const r = armarResumen(presupuestos, productos, { verCosto: true });
    const sardina = r.por_producto.find((p) => p.producto_id === 'sardina')!;
    expect(sardina).toMatchObject({ costo_unitario: 3113, costo_total: 186780, margen_pct: 33.77 });
  });

  it('por cliente y totales; los subtítulos no suman', () => {
    const r = armarResumen(presupuestos, productos, { verCosto: false });
    expect(r.por_cliente).toEqual([
      expect.objectContaining({ cliente: 'COMERCIAL B', productos: 2, cantidad: 108, monto: 464400, presupuestos: ['P-2'] }),
      expect.objectContaining({ cliente: 'COMERCIAL A', productos: 1, cantidad: 120, monto: 444000 }),
    ]);
    expect(r.totales).toEqual({ presupuestos: 2, clientes: 2, productos: 2, cantidad: 228, montos: [{ moneda: 'PYG', monto: 908400 }] });
    expect(r.detalle).toHaveLength(3);
    expect(r.detalle[0]).toMatchObject({ presupuesto: 'P-1', cliente: 'COMERCIAL A', empaques: 5, vendedor: 'Cristian Olmedo' });
  });

  it('no mezcla monedas: el mismo producto en USD va aparte y sin margen', () => {
    const r = armarResumen(
      [...presupuestos, pres('P-3', 'COMERCIAL C', [item({ producto_id: 'choclo', descripcion: 'choclo', cantidad: 24, precio_unitario: 0.5, total: 12 })], 'USD')],
      productos,
      { verCosto: true },
    );
    const usd = r.por_producto.find((p) => p.producto_id === 'choclo' && p.moneda === 'USD')!;
    expect(usd).toMatchObject({ cantidad: 24, monto: 12, costo_unitario: null, margen_pct: null });
    expect(r.totales.montos).toEqual([{ moneda: 'PYG', monto: 908400 }, { moneda: 'USD', monto: 12 }]);
  });

  it('un ítem de texto libre se agrupa por descripción', () => {
    const r = armarResumen(
      [pres('P-4', 'X', [item({ tipo: 'TEXTO_LIBRE', producto_id: null, descripcion: 'Flete ', cantidad: 1, precio_unitario: 50000, total: 50000 })]),
       pres('P-5', 'Y', [item({ tipo: 'TEXTO_LIBRE', producto_id: null, descripcion: 'flete', cantidad: 1, precio_unitario: 50000, total: 50000 })])],
      productos,
      { verCosto: false },
    );
    expect(r.por_producto).toHaveLength(1);
    expect(r.por_producto[0]).toMatchObject({ cantidad: 2, monto: 100000, clientes: 2 });
  });
});
