import { MarangatuGateway } from '../marangatu.gateway';

/**
 * Dos cosas del microservicio que condicionan este gateway:
 *  1. Sólo manda `worker_public.snapshot` como respuesta a `worker_public.subscribe`;
 *     nunca avisa solo cuando cambia el estado del worker. Sin volver a pedirlo, el
 *     panel queda congelado con lo que hubiera al arrancar el backend (en producción
 *     mostraba "pausado — Login falló por credenciales inválidas" con el worker ya
 *     desactivado a mano).
 *  2. En cada `subscribe` saca al socket de los rooms públicos anteriores, así que
 *     una sola conexión recibe los eventos en vivo de la ÚLTIMA suscripción: hace
 *     falta una conexión por empresa y tipo.
 */
describe('MarangatuGateway — refresco de snapshots', () => {
  const fakeSocket = (connected = true) => ({ connected, emit: jest.fn(), disconnect: jest.fn() });

  const crear = ({ activo = true, pares = ['80095925:COMPRA', '80095925:VENTA'], conectado = true } = {}) => {
    const gateway = Object.create(MarangatuGateway.prototype) as any;
    gateway.logger = { debug: jest.fn(), log: jest.fn(), warn: jest.fn(), error: jest.fn() };
    gateway.active = activo;
    gateway.ultimoRefresco = 0;
    gateway.conexiones = new Map(pares.map((clave) => [clave, fakeSocket(conectado)]));
    return gateway;
  };

  it('vuelve a suscribir cada empresa y tipo cuando el panel pide el estado', async () => {
    const gateway = crear();

    await gateway.handleSolicitarSnapshot();

    const emitidos = [...gateway.conexiones.values()].map((s: any) => s.emit.mock.calls[0]);
    expect(emitidos).toEqual([
      ['worker_public.subscribe', { empresaRuc: '80095925', tipoRegistro: 'COMPRA' }],
      ['worker_public.subscribe', { empresaRuc: '80095925', tipoRegistro: 'VENTA' }],
    ]);
  });

  it('no repite el pedido si llegan varios seguidos (varias pestañas abiertas)', async () => {
    const gateway = crear();

    await gateway.handleSolicitarSnapshot();
    await gateway.handleSolicitarSnapshot();
    await gateway.handleSolicitarSnapshot();

    for (const socket of gateway.conexiones.values()) {
      expect((socket as any).emit).toHaveBeenCalledTimes(1);
    }
  });

  it('vuelve a pedirlo pasado el piso entre refrescos', async () => {
    const gateway = crear();

    await gateway.handleSolicitarSnapshot();
    gateway.ultimoRefresco = Date.now() - 6_000;
    await gateway.handleSolicitarSnapshot();

    for (const socket of gateway.conexiones.values()) {
      expect((socket as any).emit).toHaveBeenCalledTimes(2);
    }
  });

  it('no le pide nada a una conexión caída', async () => {
    const gateway = crear({ conectado: false });

    await gateway.handleSolicitarSnapshot();

    for (const socket of gateway.conexiones.values()) {
      expect((socket as any).emit).not.toHaveBeenCalled();
    }
  });

  it('desactivar cierra todas las conexiones y corta el refresco', () => {
    const gateway = crear();
    gateway.refrescoTimer = setInterval(() => {}, 60_000);
    const sockets = [...gateway.conexiones.values()];

    gateway.deactivateWs();

    for (const socket of sockets) expect((socket as any).disconnect).toHaveBeenCalled();
    expect(gateway.conexiones.size).toBe(0);
    expect(gateway.refrescoTimer).toBeNull();
    expect(gateway.active).toBe(false);
  });
});
