import { ConfigService } from '@nestjs/config';
import { MetricsService } from './metrics.service';

describe('MetricsService', () => {
  const createService = (values: Record<string, number> = {}) => {
    const config = {
      get: jest.fn((key: string) => values[key]),
    } as unknown as ConfigService;
    return new MetricsService(config);
  };

  it('aggregates latency, errors, timeouts, and an approximate p95 by route', () => {
    const service = createService();
    service.observe('GET', '/feed/me', 200, 20);
    service.observe('GET', '/feed/me', 408, 40);
    service.observe('GET', '/feed/me', 500, 260);

    expect(service.snapshot().routes[0]).toEqual(
      expect.objectContaining({
        route: 'GET /feed/me',
        requests: 3,
        clientErrors: 1,
        errors: 1,
        timeouts: 1,
        errorRate: 1 / 3,
        averageDurationMs: 106.67,
        p95DurationMs: 500,
        maxDurationMs: 260,
      }),
    );
  });

  it('tracks current and peak in-flight work', () => {
    const service = createService();
    service.requestStarted();
    service.requestStarted();
    service.requestFinished('GET', '/health', 200, 2);

    expect(service.snapshot().operational).toEqual({
      totalRequests: 2,
      inFlightRequests: 1,
      peakInFlightRequests: 2,
    });
  });

  it('caps route cardinality and exposes finite event-loop metrics', () => {
    const service = createService({ 'metrics.maxRoutes': 1 });
    service.onModuleInit();
    service.observe('GET', '/first', 200, 1);
    service.observe('GET', '/second', 200, 1);
    const snapshot = service.snapshot();
    service.onModuleDestroy();

    expect(snapshot.routes.map((route) => route.route)).toEqual(
      expect.arrayContaining(['GET /first', '__other_routes__']),
    );
    expect(snapshot.eventLoop).toEqual(
      expect.objectContaining({
        healthy: expect.any(Boolean),
        utilization: expect.any(Number),
        lagP99Ms: expect.any(Number),
      }),
    );
  });
});
