import { ZoomDashboardApiClient } from './zoom-dashboard-api.client';
import { ZoomAnalyticsResourceType } from 'src/common/enum/zoom-analytics-resource-type.enum';

describe('ZoomDashboardApiClient', () => {
  const http = { get: jest.fn() };
  const logger = { warn: jest.fn() };

  let client: ZoomDashboardApiClient;

  beforeEach(() => {
    jest.clearAllMocks();
    client = new ZoomDashboardApiClient(http as any, logger as any);
  });

  it('hits the webinar metrics endpoint for a WEBINAR session', async () => {
    http.get.mockResolvedValue({ participants: [] });

    await client.fetchLiveParticipants('ext-1', ZoomAnalyticsResourceType.WEBINAR);

    expect(http.get).toHaveBeenCalledWith('/metrics/webinars/ext-1/participants', { page_size: 300 });
  });

  it('hits the meeting metrics endpoint for a MEETING session — not the webinar one', async () => {
    http.get.mockResolvedValue({ participants: [] });

    await client.fetchLiveParticipants('ext-2', ZoomAnalyticsResourceType.MEETING);

    expect(http.get).toHaveBeenCalledWith('/metrics/meetings/ext-2/participants', { page_size: 300 });
  });

  it('returns the participants array from the response', async () => {
    const participants = [{ email: 'a@x.com', user_name: 'Alice' }];
    http.get.mockResolvedValue({ participants });

    const result = await client.fetchLiveParticipants('ext-1', ZoomAnalyticsResourceType.WEBINAR);

    expect(result).toEqual(participants);
  });

  it.each([401, 403, 404])(
    'degrades gracefully (returns null, warns once) on a %d response instead of throwing',
    async (status) => {
      http.get.mockRejectedValue({ response: { status } });

      const result = await client.fetchLiveParticipants('ext-1', ZoomAnalyticsResourceType.WEBINAR);

      expect(result).toBeNull();
      expect(logger.warn).toHaveBeenCalledTimes(1);
    },
  );

  it('only warns once across repeated unavailable calls, not every poll tick', async () => {
    http.get.mockRejectedValue({ response: { status: 403 } });

    await client.fetchLiveParticipants('ext-1', ZoomAnalyticsResourceType.WEBINAR);
    await client.fetchLiveParticipants('ext-1', ZoomAnalyticsResourceType.WEBINAR);

    expect(logger.warn).toHaveBeenCalledTimes(1);
  });

  it('rethrows on an unexpected error status rather than silently swallowing it', async () => {
    http.get.mockRejectedValue({ response: { status: 500 } });

    await expect(
      client.fetchLiveParticipants('ext-1', ZoomAnalyticsResourceType.WEBINAR),
    ).rejects.toBeDefined();
  });
});

