import { StockService } from './stock.service';

/**
 * Stock por depósito muestra costo y precio de venta:
 *  - costo: promedio ponderado de los lotes con stock en ESE depósito si el
 *    producto maneja lotes; si no, `productos.precio_costo`.
 *  - venta: `precio_base` de la lista general de la empresa; si el producto
 *    no está en la lista, `productos.precio`.
 */
describe('StockService.findByDeposito - precios', () => {
  const DEP = 'dep-1';
  const filas = [
    { producto_id: 'p-lote', deposito_id: DEP, cantidad_disponible: 10, producto: { id: 'p-lote', maneja_lote: true, precio_costo: 900, precio: 2000 } },
    { producto_id: 'p-simple', deposito_id: DEP, cantidad_disponible: 3, producto: { id: 'p-simple', maneja_lote: false, precio_costo: 500, precio: 1500 } },
    { producto_id: 'p-sin-precio', deposito_id: DEP, cantidad_disponible: 1, producto: { id: 'p-sin-precio', maneja_lote: true, precio_costo: null, precio: null } },
  ];

  const crearPrisma = ({ lista = true } = {}) => ({
    stock_deposito: { findMany: jest.fn().mockResolvedValue(filas) },
    stock_lote: {
      findMany: jest.fn().mockResolvedValue([
        // p-lote: 4 u. a 1000 + 6 u. a 1200 → promedio ponderado 1120
        { lotes_producto: { producto_id: 'p-lote', costo_unitario: 1000 }, cantidad_disponible: 4 },
        { lotes_producto: { producto_id: 'p-lote', costo_unitario: 1200 }, cantidad_disponible: 6 },
      ]),
    },
    lista_precios: {
      findFirst: jest.fn().mockResolvedValue(
        lista
          ? {
              id: 'lista-1',
              nombre: 'Lista General',
              moneda: 'PYG',
              lista_precios_productos: [{ producto_id: 'p-lote', precio_base: 2500 }],
            }
          : null,
      ),
    },
    empresa_monedas: { findFirst: jest.fn().mockResolvedValue({ moneda: { codigo: 'PYG' } }) },
  });

  it('costo de lotes (promedio ponderado por depósito) y venta de la lista general', async () => {
    const prisma: any = crearPrisma();
    const r: any[] = await new StockService(prisma, {} as any).findByDeposito(DEP, 'emp');
    expect(r[0].precios).toEqual({
      costo: { valor: 1120, moneda: 'PYG', fuente: 'lote' },
      venta: { valor: 2500, moneda: 'PYG', fuente: 'lista', lista: 'Lista General' },
    });
    // La consulta de lotes se limita al depósito pedido.
    expect(prisma.stock_lote.findMany.mock.calls[0][0].where).toMatchObject({ deposito_id: DEP });
  });

  it('sin lotes cae al costo del producto; sin precio en lista cae al precio base', async () => {
    const prisma: any = crearPrisma();
    const r: any[] = await new StockService(prisma, {} as any).findByDeposito(DEP, 'emp');
    expect(r[1].precios).toEqual({
      costo: { valor: 500, moneda: 'PYG', fuente: 'producto' },
      venta: { valor: 1500, moneda: 'PYG', fuente: 'producto', lista: null },
    });
  });

  it('maneja lotes pero sin stock en lotes de este depósito → costo del producto; sin ningún precio → null', async () => {
    const prisma: any = crearPrisma({ lista: false });
    const r: any[] = await new StockService(prisma, {} as any).findByDeposito(DEP, 'emp');
    expect(r[2].precios).toEqual({
      costo: { valor: null, moneda: 'PYG', fuente: 'producto' },
      venta: { valor: null, moneda: 'PYG', fuente: 'producto', lista: null },
    });
  });
});
