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

// Mock auth
vi.mock('@/lib/auth', () => ({
  auth: vi.fn(),
}));

// Mock analytics
vi.mock('@/lib/token/analytics', () => ({
  getTokenSpending: vi.fn(),
  getCloudSpending: vi.fn(),
  getSavingsEstimate: vi.fn(),
  formatSpendingContext: vi.fn(),
}));

// Mock logger
vi.mock('@/lib/logger', () => ({
  logger: { info: vi.fn(), error: vi.fn(), warn: vi.fn(), debug: vi.fn() },
}));

import { auth } from '@/lib/auth';
import {
  getTokenSpending,
  getCloudSpending,
  getSavingsEstimate,
  formatSpendingContext,
} from '@/lib/token/analytics';

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

  it('should return 401 when not authenticated', async () => {
    vi.mocked(auth).mockResolvedValue(null as any);

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

    expect(response.status).toBe(401);
    expect(data.error).toBe('Unauthorized');
    expect(getTokenSpending).not.toHaveBeenCalled();
  });

  it('should return analytics data when authenticated', async () => {
    vi.mocked(auth).mockResolvedValue({
      user: { id: 'user_1', email: 'test@test.com' },
    } as any);

    const mockTokenSpending = {
      today: 0.01,
      thisMonth: 0.1,
      allTime: 1.0,
      byModel: { 'gemini-flash': 0.5 },
      byIntent: { chat: 0.8 },
      messageCount: 50,
      budgetUsedPct: 20,
      budgetRemaining: 40,
    };

    const mockCloudSpending = {
      thisMonth: 25.0,
      lastMonth: 20.0,
      byProvider: { openai: 25.0 },
      trend: 'up' as const,
    };

    const mockSavings = {
      tokenCostUsd: 1.0,
      equivalentCloudCost: 5.0,
      savingsUsd: 4.0,
      savingsPct: 80.0,
    };

    vi.mocked(getTokenSpending).mockResolvedValue(mockTokenSpending as any);
    vi.mocked(getCloudSpending).mockResolvedValue(mockCloudSpending as any);
    vi.mocked(getSavingsEstimate).mockResolvedValue(mockSavings as any);
    vi.mocked(formatSpendingContext).mockReturnValue('formatted context');

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

    expect(response.status).toBe(200);
    expect(data.tokenSpending).toEqual(mockTokenSpending);
    expect(data.cloudSpending).toEqual(mockCloudSpending);
    expect(data.savings).toEqual(mockSavings);
    expect(data.formatted).toBe('formatted context');

    expect(getTokenSpending).toHaveBeenCalledWith('user_1');
    expect(getCloudSpending).toHaveBeenCalledWith('user_1');
    expect(getSavingsEstimate).toHaveBeenCalledWith('user_1');
    expect(formatSpendingContext).toHaveBeenCalledWith(mockTokenSpending, mockCloudSpending, mockSavings);
  });

  it('should return 500 on analytics error', async () => {
    vi.mocked(auth).mockResolvedValue({
      user: { id: 'user_1', email: 'test@test.com' },
    } as any);

    vi.mocked(getTokenSpending).mockRejectedValue(new Error('DB connection failed'));

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

    expect(response.status).toBe(500);
    expect(data.error).toBe('Failed to load analytics');
  });
});
