import { envs } from 'src/config';
import { MiddlewareSifenService } from './middleware-sifen.service';

/**
 * Con el middleware caído (falla el login) los eventos pendientes igual se
 * clasifican: una incoherencia o un evento que no se puede consultar hace más
 * de una hora tiene que generar su alerta. Ver docs/plan-alertas-empresa.md.
 */
describe('MiddlewareSifenService.sincronizarSifen - login al middleware falla', () => {
  const urlOriginal = envs.middlewareSifenUrl;
  beforeAll(() => {
    (envs as any).middlewareSifenUrl = 'http://middleware.test';
  });
  afterAll(() => {
    (envs as any).middlewareSifenUrl = urlOriginal;
  });

  const evento = (extra: Record<string, unknown>) => ({
    id: 'fac-1',
    empresa_id: 'emp-1',
    cdc: 'CDC-1',
    dest: '001',
    dpunexp: '001',
    dnumdoc: '0000002',
    estado_sifen: 'Aprobado',
    evento_aplicado: 'ECAN',
    estado_evento: 'Pendiente',
    ...extra,
  });

  const crearService = (eventos: Array<Record<string, unknown>>, documentos: Array<Record<string, unknown>> = []) => {
    const prisma: any = {
      factura_cab: {
        findMany: jest.fn(({ where }) => Promise.resolve(where.estado_evento ? eventos : documentos)),
        update: jest.fn(),
      },
      empresas_sucursales: { findMany: jest.fn().mockResolvedValue([]) },
    };
    const alertas = { registrar: jest.fn().mockResolvedValue({ id: 'al-1', creada: true }), resolver: jest.fn() };
    const service = new MiddlewareSifenService(
      {} as any,
      prisma,
      { log: jest.fn() } as any,
      {} as any,
      {} as any,
      {} as any,
      {} as any,
      alertas as any,
      {} as any,
    );
    jest.spyOn(service, 'login').mockRejectedValue(new Error('middleware caído'));
    const fetchSpy = jest.fn();
    global.fetch = fetchSpy as any;
    return { service, alertas, fetchSpy };
  };

  it('evento incoherente: registra la alerta sin consultar el middleware', async () => {
    const { service, alertas, fetchSpy } = crearService([
      evento({ evento_aplicado: 'EINU', fecha_evento: null }),
    ]);

    const res = await service.sincronizarSifen('emp-1', 'factura', 'evento');

    expect(res.casosEvento['fac-1']).toBe('incoherente');
    expect(alertas.registrar).toHaveBeenCalledTimes(1);
    expect(fetchSpy).not.toHaveBeenCalled();
  });

  it('evento de más de 1 h: queda como middleware_falla y alerta', async () => {
    const { service, alertas } = crearService([evento({ fecha_evento: new Date(Date.now() - 2 * 3600_000) })]);

    const res = await service.sincronizarSifen('emp-1', 'factura', 'evento');

    expect(res.casosEvento['fac-1']).toBe('middleware_falla');
    expect(res.detalles.join(' ')).toContain('middleware caído');
    expect(alertas.registrar).toHaveBeenCalledTimes(1);
  });

  it('evento reciente: en espera, sin alerta', async () => {
    const { service, alertas } = crearService([evento({ fecha_evento: new Date() })]);

    const res = await service.sincronizarSifen('emp-1', 'factura', 'evento');

    expect(res.casosEvento['fac-1']).toBe('en_espera');
    expect(alertas.registrar).not.toHaveBeenCalled();
  });

  it('sin eventos pendientes el error de login se propaga como antes', async () => {
    const { service } = crearService([], [{ id: 'fac-2', nro_lote: 'lote-1' }]);

    await expect(service.sincronizarSifen('emp-1', 'factura', 'documento')).rejects.toThrow('middleware caído');
  });
});
