import { ViajeCalculosService } from '../viaje-calculos.service';
import { ViajeDocumentosService } from '../viaje-documentos.service';

describe('No se enganchan documentos dados de baja', () => {
  const crear = (tabla: string, doc: any) => {
    const prisma: any = {
      usuario: { findUnique: jest.fn().mockResolvedValue({ is_superadmin: true }) },
      empresas: { findUnique: jest.fn().mockResolvedValue({ type: 'subsidiary' }) },
      rubros: { findFirst: jest.fn().mockResolvedValue(null) },
      asignacion_sucursal_caja_usuario: { findMany: jest.fn().mockResolvedValue([]) },
      empresas_sucursales: { findMany: jest.fn().mockResolvedValue([]) },
      depositos: { findMany: jest.fn().mockResolvedValue([]) },
      viaje_documentos: { findFirst: jest.fn().mockResolvedValue(null), createMany: jest.fn() },
      factura_cab: { findFirst: jest.fn().mockResolvedValue(null) },
      nota_credito_cab: { findFirst: jest.fn().mockResolvedValue(null) },
      nota_remision_cab: { findFirst: jest.fn().mockResolvedValue(null) },
      recibos_cobro: { findFirst: jest.fn().mockResolvedValue(null) },
      pedidos: { findFirst: jest.fn().mockResolvedValue(null) },
      presupuesto_cab: { findFirst: jest.fn().mockResolvedValue(null) },
    };
    prisma[tabla].findFirst = jest.fn().mockResolvedValue(doc);
    const viajes: any = {
      exigirEditable: jest.fn().mockResolvedValue({ id: 'v-1', estado: 'EN_RUTA' }),
      findOne: jest.fn().mockResolvedValue({ id: 'v-1', estado: 'EN_RUTA', documentos: [] }),
    };
    const service = Object.create(ViajeDocumentosService.prototype) as any;
    service.prisma = prisma;
    service.viajes = viajes;
    return service;
  };

  it('una orden de venta CANCELADA no se engancha', async () => {
    const s = crear('pedidos', { id: 'p-1', estado: 'cancelado' });
    await expect(
      s.agregar('v-1', [{ tipo: 'PEDIDO', documento_id: 'p-1' }], 'emp-1', 'u-1'),
    ).rejects.toThrow(/dado de baja/i);
  });

  it('un presupuesto RECHAZADO no se engancha', async () => {
    const s = crear('presupuesto_cab', { id: 'pr-1', estado: 'REJECTED' });
    await expect(
      s.agregar('v-1', [{ tipo: 'PRESUPUESTO', documento_id: 'pr-1' }], 'emp-1', 'u-1'),
    ).rejects.toThrow(/dado de baja/i);
  });

  it('un presupuesto VENCIDO no se engancha', async () => {
    const s = crear('presupuesto_cab', { id: 'pr-2', estado: 'EXPIRED' });
    await expect(
      s.agregar('v-1', [{ tipo: 'PRESUPUESTO', documento_id: 'pr-2' }], 'emp-1', 'u-1'),
    ).rejects.toThrow(/dado de baja/i);
  });

  it('una orden de venta CONFIRMADA sí se engancha', async () => {
    const s = crear('pedidos', { id: 'p-2', estado: 'confirmado' });
    await expect(
      s.agregar('v-1', [{ tipo: 'PEDIDO', documento_id: 'p-2' }], 'emp-1', 'u-1'),
    ).resolves.toBeDefined();
  });
});

describe('lineasPlanificadas — presupuestos junto a órdenes de venta', () => {
  it('sólo descarta el presupuesto que YA derivó en un pedido del viaje', async () => {
    const prisma: any = {
      pedido_detalle: {
        findMany: jest.fn().mockResolvedValue([
          { producto_id: 'p-1', cantidad_base: 480, producto: { descripcion: 'NARANJA', cod_producto: null },
            pedido: { cliente_id: 'cli-1', cliente: { personas: { razon_social: 'CLI-1' } } } },
        ]),
      },
      presupuesto_det: {
        findMany: jest.fn().mockResolvedValue([
          // Este presupuesto YA derivó en ped-1, que está en el viaje: se descarta.
          { producto_id: 'p-1', cantidad: 480, productos: { descripcion: 'NARANJA', cod_producto: null },
            presupuesto: { cliente_id: 'cli-1', pedido_id: 'ped-1', clientes: { personas: { razon_social: 'CLI-1' } } } },
          // Este NO tiene orden: su planificado tiene que contarse.
          { producto_id: 'p-2', cantidad: 240, productos: { descripcion: 'MANZANA', cod_producto: null },
            presupuesto: { cliente_id: 'cli-2', pedido_id: null, clientes: { personas: { razon_social: 'CLI-2' } } } },
        ]),
      },
    };
    const documentos: any = {
      idsPorTipo: jest.fn().mockImplementation((_id, tipo) =>
        Promise.resolve(tipo === 'PEDIDO' ? ['ped-1'] : tipo === 'PRESUPUESTO' ? ['pr-1', 'pr-2'] : []),
      ),
    };
    const service = Object.create(ViajeCalculosService.prototype) as any;
    service.prisma = prisma;
    // Los cálculos piden solo los vigentes; acá el filtro de bajas no es lo que se prueba.
    documentos.idsVigentes ??= documentos.idsPorTipo;
    service.documentos = documentos;

    const { lineas } = await service.lineasPlanificadas('v-1');

    // La naranja una sola vez (del pedido) y la manzana del presupuesto suelto.
    expect(lineas).toHaveLength(2);
    expect(lineas.find((l: any) => l.producto_id === 'p-1').cantidad_base).toBe(480);
    expect(lineas.find((l: any) => l.producto_id === 'p-2').cantidad_base).toBe(240);
  });
});
