import { CobranzasJobsService } from './cobranzas-jobs.service';

describe('CobranzasJobsService — jobs bajo advisory lock', () => {
  const crearService = (lockAdquirido: boolean) => {
    const tx = { $queryRaw: jest.fn().mockResolvedValue([{ locked: lockAdquirido }]) };
    const prisma: any = {
      $transaction: jest.fn((fn: (tx: any) => Promise<unknown>) => fn(tx)),
    };
    const promesasService: any = {
      marcarIncumplidas: jest.fn().mockResolvedValue(undefined),
      getPromesasParaRecordatorio: jest.fn().mockResolvedValue([]),
    };
    const autorizacionesService: any = { expirarVencidas: jest.fn().mockResolvedValue(undefined) };
    const interesesMoratoriosService: any = {
      listarRecibosConEmisionPendiente: jest.fn().mockResolvedValue([]),
    };
    const gestionMoraService: any = {
      autoAbrirGestionesVencidas: jest.fn().mockResolvedValue({ abiertas: 0, errores: [] }),
    };
    const service = new CobranzasJobsService(
      promesasService,
      autorizacionesService,
      interesesMoratoriosService,
      gestionMoraService,
      {} as any,
      {} as any,
      prisma,
    );
    return { service, tx, promesasService, autorizacionesService, interesesMoratoriosService, gestionMoraService };
  };

  const casos: Array<
    [string, (s: ReturnType<typeof crearService>) => Promise<void>, (s: ReturnType<typeof crearService>) => jest.Mock]
  > = [
    [
      'autoAbrirGestionesMora',
      (s) => s.service.autoAbrirGestionesMora(),
      (s) => s.gestionMoraService.autoAbrirGestionesVencidas,
    ],
    ['expirarAutorizaciones', (s) => s.service.expirarAutorizaciones(), (s) => s.autorizacionesService.expirarVencidas],
    ['procesarPromesas', (s) => s.service.procesarPromesas(), (s) => s.promesasService.marcarIncumplidas],
    [
      'reintentarEmisionInteresesMoratorios',
      (s) => s.service.reintentarEmisionInteresesMoratorios(),
      (s) => s.interesesMoratoriosService.listarRecibosConEmisionPendiente,
    ],
  ];

  describe.each(casos)('%s', (_nombre, correr, trabajo) => {
    it('corre el trabajo cuando obtiene el lock de la DB', async () => {
      const s = crearService(true);
      await correr(s);
      expect(s.tx.$queryRaw).toHaveBeenCalledTimes(1);
      expect(trabajo(s)).toHaveBeenCalledTimes(1);
    });

    it('no corre el trabajo si otra instancia ya tiene el lock', async () => {
      const s = crearService(false);
      await correr(s);
      expect(trabajo(s)).not.toHaveBeenCalled();
    });
  });
});
