/**
 * Tests for frontend metrics collection.
 */

import { describe, it, expect, beforeEach, vi } from 'vitest';
import {
  initializeWebVitals,
  recordApiCall,
  getCollectedMetrics,
  resetMetrics,
  exportMetrics,
} from '../metrics';

describe('Metrics', () => {
  beforeEach(() => {
    resetMetrics();
  });

  describe('recordApiCall', () => {
    it('should record an API call metric', () => {
      recordApiCall('GET', '/api/jails', 200, 42);

      const metrics = getCollectedMetrics();
      expect(metrics.apiCalls).toHaveLength(1);
      expect(metrics.apiCalls[0]).toMatchObject({
        method: 'GET',
        endpoint: '/api/jails',
        statusCode: 200,
        durationMs: 42,
      });
      expect(metrics.apiCalls[0]?.timestamp || 0).toBeGreaterThan(0);
    });

    it('should record multiple API calls', () => {
      recordApiCall('GET', '/api/jails', 200, 42);
      recordApiCall('POST', '/api/bans', 201, 100);

      const metrics = getCollectedMetrics();
      expect(metrics.apiCalls).toHaveLength(2);
    });

    it('should track error responses', () => {
      recordApiCall('GET', '/api/notfound', 404, 10);

      const metrics = getCollectedMetrics();
      expect(metrics.apiCalls[0]?.statusCode).toBe(404);
    });
  });

  describe('getCollectedMetrics', () => {
    it('should return empty metrics initially', () => {
      const metrics = getCollectedMetrics();
      expect(metrics.vitals).toHaveLength(0);
      expect(metrics.apiCalls).toHaveLength(0);
    });

    it('should return collected metrics', () => {
      recordApiCall('GET', '/api/test', 200, 50);

      const metrics = getCollectedMetrics();
      expect(metrics.apiCalls).toHaveLength(1);
    });
  });

  describe('resetMetrics', () => {
    it('should clear all collected metrics', () => {
      recordApiCall('GET', '/api/test', 200, 50);
      expect(getCollectedMetrics().apiCalls).toHaveLength(1);

      resetMetrics();
      expect(getCollectedMetrics().apiCalls).toHaveLength(0);
    });
  });

  describe('exportMetrics', () => {
    it('should skip export when no metrics are collected', async () => {
      const fetchSpy = vi.spyOn(global, 'fetch');

      await exportMetrics();

      expect(fetchSpy).not.toHaveBeenCalled();
      fetchSpy.mockRestore();
    });

    it('should export collected metrics', async () => {
      recordApiCall('GET', '/api/test', 200, 50);

      global.fetch = vi.fn().mockResolvedValue({ ok: true });

      await exportMetrics();

      expect(global.fetch).toHaveBeenCalledWith(
        '/api/metrics/events',
        expect.objectContaining({
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
        }),
      );
    });

    it('should handle fetch errors gracefully', async () => {
      recordApiCall('GET', '/api/test', 200, 50);

      global.fetch = vi.fn().mockRejectedValue(new Error('Network error'));

      // Should not throw
      await expect(exportMetrics()).resolves.toBeUndefined();
    });
  });

  describe('initializeWebVitals', () => {
    it('should be callable', () => {
      // initializeWebVitals should be a callable function
      expect(typeof initializeWebVitals).toBe('function');
    });
  });
});
