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

describe('ViajeDocumentosService', () => {
  const viaje = {
    id: 'v-1',
    empresa_id: 'emp-1',
    estado: 'EN_RUTA',
    vendedor_id: 'vend-1',
    fecha_salida: new Date('2026-09-20'),
    fecha_retorno: new Date('2026-09-22'),
  };

  const crear = (extra: 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: {
        findMany: jest.fn().mockResolvedValue([]),
        createMany: jest.fn().mockResolvedValue({ count: 1 }),
        findFirst: jest.fn().mockResolvedValue(null),
        delete: jest.fn().mockResolvedValue({}),
        ...extra.viaje_documentos,
      },
      factura_cab: { findMany: jest.fn().mockResolvedValue([]), findFirst: jest.fn().mockResolvedValue(null), ...extra.factura_cab },
      nota_remision_cab: { findMany: jest.fn().mockResolvedValue([]), findFirst: jest.fn().mockResolvedValue(null) },
      nota_credito_cab: { findMany: jest.fn().mockResolvedValue([]), findFirst: jest.fn().mockResolvedValue(null) },
      recibos_cobro: { findMany: jest.fn().mockResolvedValue([]), findFirst: jest.fn().mockResolvedValue(null) },
      pedidos: { findMany: jest.fn().mockResolvedValue([]), findFirst: jest.fn().mockResolvedValue(null) },
      presupuesto_cab: { findMany: jest.fn().mockResolvedValue([]), findFirst: jest.fn().mockResolvedValue(null) },
    };
    const viajes: any = { exigirEditable: jest.fn().mockResolvedValue(viaje), findOne: jest.fn().mockResolvedValue(viaje) };
    const service = Object.create(ViajeDocumentosService.prototype) as any;
    service.prisma = prisma;
    service.viajes = viajes;
    return { service, prisma };
  };

  it('sugiere facturas del vendedor dentro de las fechas y excluye las ya asignadas', async () => {
    const { service, prisma } = crear({
      factura_cab: {
        findMany: jest.fn().mockResolvedValue([
          { id: 'f-1', dest: '001', dpunexp: '001', dnumdoc: '0000001', dfeemide: new Date('2026-09-21'),
            moneda: { codigo: 'PYG' }, clientes: { personas: { razon_social: 'CLIENTE UNO' } },
            factura_subtotales: [{ dtotgralope: 1_000_000 }] },
        ]),
      },
    });

    const r = await service.sugeridos('v-1', 'emp-1', 'usr-1');

    expect(r.facturas).toEqual([
      expect.objectContaining({ id: 'f-1', tipo: 'FACTURA', numero: '001-001-0000001', total: 1_000_000, moneda: 'PYG' }),
    ]);
    const where = prisma.factura_cab.findMany.mock.calls[0][0].where;
    expect(where.empresa_id).toBe('emp-1');
    expect(where.vendedor_id).toBe('vend-1');
    expect(where.estado.notIn).toEqual(expect.arrayContaining(['Anulado']));
    expect(where.id.notIn).toEqual([]);
  });

  it('no engancha un documento de otra empresa', async () => {
    const { service } = crear();
    await expect(
      service.agregar('v-1', [{ tipo: 'FACTURA', documento_id: 'f-ajena' }], 'emp-1', 'usr-1'),
    ).rejects.toThrow(/no encontrado|otra empresa/i);
  });

  it('no engancha un documento ya asignado a otro viaje', async () => {
    const { service } = crear({
      factura_cab: { findFirst: jest.fn().mockResolvedValue({ id: 'f-1', estado: 'Aprobado' }) },
      viaje_documentos: { findFirst: jest.fn().mockResolvedValue({ id: 'vd-9', viaje_id: 'v-2' }) },
    });
    await expect(
      service.agregar('v-1', [{ tipo: 'FACTURA', documento_id: 'f-1' }], 'emp-1', 'usr-1'),
    ).rejects.toThrow(/ya está en otro viaje/i);
  });

  it('no engancha un documento anulado', async () => {
    const { service } = crear({
      factura_cab: { findFirst: jest.fn().mockResolvedValue({ id: 'f-1', estado: 'Anulado' }) },
    });
    await expect(
      service.agregar('v-1', [{ tipo: 'FACTURA', documento_id: 'f-1' }], 'emp-1', 'usr-1'),
    ).rejects.toThrow(/anulado/i);
  });

  it('marca el presupuesto que ya derivó en una orden de venta', async () => {
    const { service } = crear({});
    (service as any).prisma.presupuesto_cab.findMany = jest.fn().mockResolvedValue([
      { id: 'pr-1', numero: 'PR-1', fecha_emision: new Date('2026-09-21'), total: 500_000, pedido_id: 'ped-1',
        moneda: { codigo: 'PYG' }, clientes: { personas: { razon_social: 'CLI-1' } } },
    ]);

    const r = await service.sugeridos('v-1', 'emp-1', 'usr-1');

    expect(r.presupuestos[0]).toEqual(expect.objectContaining({ id: 'pr-1', ya_tiene_orden: true }));
  });

  it('engancha y marca si vino de la propuesta automática', async () => {
    const { service, prisma } = crear({
      factura_cab: { findFirst: jest.fn().mockResolvedValue({ id: 'f-1', estado: 'Aprobado' }) },
    });
    await service.agregar('v-1', [{ tipo: 'FACTURA', documento_id: 'f-1', agregado_auto: true }], 'emp-1', 'usr-1');
    const data = prisma.viaje_documentos.createMany.mock.calls[0][0].data;
    expect(data).toEqual([
      expect.objectContaining({ viaje_id: 'v-1', tipo: 'FACTURA', documento_id: 'f-1', agregado_auto: true }),
    ]);
  });
});
