import { clasificarEventoPendiente, incoherenciaEvento, UMBRAL_EVENTO_MS } from './clasificar-evento-pendiente';

/**
 * Qué le pasó a un evento SIFEN que sigue Pendiente. Ver docs/plan-alertas-empresa.md.
 */
describe('clasificarEventoPendiente', () => {
  const ahora = new Date('2026-09-15T12:00:00Z');
  const hace = (ms: number) => new Date(ahora.getTime() - ms);
  const minutos = (n: number) => n * 60 * 1000;

  const ecanAprobada = { evento_aplicado: 'ECAN', estado_sifen: 'Aprobado', fecha_evento: hace(minutos(10)) };
  const tieneEvento = (estado: string | null) => ({ ok: true as const, registro: { retorno_sifen: { estado } } });

  describe('incoherencias', () => {
    it('evento sin fecha', () => {
      const doc = { ...ecanAprobada, fecha_evento: null };
      expect(incoherenciaEvento(doc)).toContain('fecha');
      expect(clasificarEventoPendiente(doc, { ok: true, registro: null }, ahora).caso).toBe('incoherente');
    });

    it('si SIFEN ya dio respuesta definitiva, se aplica aunque el documento sea incoherente', () => {
      const doc = { ...ecanAprobada, fecha_evento: null };
      expect(clasificarEventoPendiente(doc, tieneEvento('Aprobado'), ahora).caso).toBe('respondido');
    });

    it('ganan sobre una falla del middleware reciente', () => {
      const doc = { evento_aplicado: 'EINU', estado_sifen: 'Aprobado', fecha_evento: hace(minutos(1)) };
      expect(clasificarEventoPendiente(doc, { ok: false, error: 'x' }, ahora).caso).toBe('incoherente');
    });

    it('inutilización sobre un documento aprobado', () => {
      const doc = { evento_aplicado: 'EINU', estado_sifen: 'Aprobado', fecha_evento: hace(minutos(5)) };
      expect(clasificarEventoPendiente(doc, null, ahora).caso).toBe('incoherente');
    });

    it('cancelación sobre un documento no aprobado', () => {
      const doc = { evento_aplicado: 'ECAN', estado_sifen: 'Rechazado', fecha_evento: hace(minutos(5)) };
      expect(clasificarEventoPendiente(doc, null, ahora).caso).toBe('incoherente');
    });

    it('nominación sobre un documento no aprobado', () => {
      const doc = { evento_aplicado: 'EINO', estado_sifen: 'Enviado', fecha_evento: hace(minutos(5)) };
      expect(clasificarEventoPendiente(doc, null, ahora).caso).toBe('incoherente');
    });

    it('inutilización sobre un rechazado es coherente', () => {
      expect(incoherenciaEvento({ evento_aplicado: 'EINU', estado_sifen: 'Rechazado', fecha_evento: hace(1) })).toBeNull();
    });
  });

  it('SIFEN respondió', () => {
    expect(clasificarEventoPendiente(ecanAprobada, tieneEvento('Rechazado'), ahora).caso).toBe('respondido');
  });

  it('el middleware no tiene el evento: no registrado, sin esperar', () => {
    expect(clasificarEventoPendiente(ecanAprobada, { ok: true, registro: null }, ahora).caso).toBe('no_registrado');
  });

  describe('sin respuesta de SIFEN', () => {
    it('antes de la hora es espera normal', () => {
      const doc = { ...ecanAprobada, fecha_evento: hace(minutos(59)) };
      expect(clasificarEventoPendiente(doc, tieneEvento(null), ahora).caso).toBe('en_espera');
    });

    it('justo en el umbral todavía espera', () => {
      const doc = { ...ecanAprobada, fecha_evento: hace(UMBRAL_EVENTO_MS) };
      expect(clasificarEventoPendiente(doc, tieneEvento(null), ahora).caso).toBe('en_espera');
    });

    it('pasada la hora es inconsistencia', () => {
      const doc = { ...ecanAprobada, fecha_evento: hace(minutos(61)) };
      expect(clasificarEventoPendiente(doc, { ok: true, registro: {} }, ahora).caso).toBe('sin_respuesta');
    });
  });

  describe('el middleware falla', () => {
    it('una caída breve no alerta', () => {
      const doc = { ...ecanAprobada, fecha_evento: hace(minutos(30)) };
      expect(clasificarEventoPendiente(doc, { ok: false, error: 'timeout' }, ahora).caso).toBe('en_espera');
    });

    it('un evento de más de una hora que no se puede consultar alerta', () => {
      const doc = { ...ecanAprobada, fecha_evento: hace(minutos(120)) };
      const r = clasificarEventoPendiente(doc, { ok: false, error: 'HTTP 502' }, ahora);
      expect(r.caso).toBe('middleware_falla');
      expect(r.detalle).toContain('HTTP 502');
    });
  });

  it('sin consulta y documento coherente, espera', () => {
    expect(clasificarEventoPendiente(ecanAprobada, null, ahora).caso).toBe('en_espera');
  });
});
