import { describe, it, expect, beforeEach, vi } from 'vitest';
import { GET } from '@/app/api/metrics/route';

// Mock fetch globally
global.fetch = vi.fn();

describe('/api/metrics', () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it('should return metrics from backend successfully', async () => {
    // Arrange
    const mockMetrics = {
      uptime: 3600,
      requests_total: 150,
      rpm: 25,
      cache_hit_rate: 0.75,
      avg_latency: 120,
      savings_total: 45.50,
      by_backend: {
        openai: { requests: 100, cost: 10.00 },
        anthropic: { requests: 50, cost: 5.00 },
      },
      by_model: [
        { model: 'gpt-4', requests: 100, cost: 10.00 },
      ],
    };

    vi.mocked(global.fetch).mockResolvedValue({
      ok: true,
      json: async () => mockMetrics,
      status: 200,
      statusText: 'OK',
    } as Response);

    // Act
    const response = await GET();
    const data = await response.json();

    // Assert
    expect(response.status).toBe(200);
    expect(data).toEqual(mockMetrics);
    expect(global.fetch).toHaveBeenCalledWith(
      'http://llmhosts:4000/api/metrics',
      expect.objectContaining({
        headers: { Accept: 'application/json' },
      })
    );
  });

  it('should return empty metrics when backend returns error status', async () => {
    // Arrange
    vi.mocked(global.fetch).mockResolvedValue({
      ok: false,
      status: 500,
      statusText: 'Internal Server Error',
    } as Response);

    // Act
    const response = await GET();
    const data = await response.json();

    // Assert
    expect(response.status).toBe(200); // Still returns 200 with empty metrics
    expect(data).toEqual({
      uptime: 0,
      requests_total: 0,
      rpm: 0,
      cache_hit_rate: 0,
      avg_latency: 0,
      savings_total: 0,
      by_backend: {},
      by_model: [],
    });
  });

  it('should return empty metrics when backend is unreachable', async () => {
    // Arrange
    vi.mocked(global.fetch).mockRejectedValue(new Error('Network error'));

    // Act
    const response = await GET();
    const data = await response.json();

    // Assert
    expect(response.status).toBe(200); // Still returns 200 with empty metrics
    expect(data).toEqual({
      uptime: 0,
      requests_total: 0,
      rpm: 0,
      cache_hit_rate: 0,
      avg_latency: 0,
      savings_total: 0,
      by_backend: {},
      by_model: [],
    });
  });

  it('should use custom backend URL from environment', async () => {
    // Arrange
    const originalEnv = process.env.LLMHOSTS_BACKEND_URL;
    process.env.LLMHOSTS_BACKEND_URL = 'http://custom-backend:8080';

    const mockMetrics = {
      uptime: 100,
      requests_total: 10,
      rpm: 5,
      cache_hit_rate: 0.5,
      avg_latency: 50,
      savings_total: 10.00,
      by_backend: {},
      by_model: [],
    };

    vi.mocked(global.fetch).mockResolvedValue({
      ok: true,
      json: async () => mockMetrics,
      status: 200,
      statusText: 'OK',
    } as Response);

    // Act
    await GET();

    // Assert
    expect(global.fetch).toHaveBeenCalledWith(
      'http://custom-backend:8080/api/metrics',
      expect.any(Object)
    );

    // Cleanup
    process.env.LLMHOSTS_BACKEND_URL = originalEnv;
  });
});
