import { renderHook, waitFor } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import React from 'react';
import { http, HttpResponse } from 'msw';
import { setupServer } from 'msw/node';
import { useStats } from '@/hooks/useStats';
import type { UsageStats, StatsQueryParams } from '@/types';

// Test data
const mockStats: UsageStats[] = [
  {
    id: 1,
    providerId: 'provider-1',
    modelName: 'gpt-4o',
    requestCount: 100,
    date: '2026-04-01',
  },
  {
    id: 2,
    providerId: 'provider-1',
    modelName: 'gpt-4o-mini',
    requestCount: 50,
    date: '2026-04-01',
  },
];

const mockFilteredStats: UsageStats[] = [
  {
    id: 3,
    providerId: 'provider-2',
    modelName: 'claude-sonnet-4-5',
    requestCount: 200,
    date: '2026-04-01',
  },
];

// Track the request URL for assertions
let capturedUrl: URL | null = null;

// MSW handlers
const handlers = [
  http.get('/api/stats', ({ request }) => {
    capturedUrl = new URL(request.url);
    const providerId = capturedUrl.searchParams.get('provider_id');
    if (providerId === 'provider-2') {
      return HttpResponse.json(mockFilteredStats);
    }
    return HttpResponse.json(mockStats);
  }),
];

const server = setupServer(...handlers);

function createTestQueryClient() {
  return new QueryClient({
    defaultOptions: {
      queries: { retry: false },
      mutations: { retry: false },
    },
  });
}

function createWrapper() {
  const testQueryClient = createTestQueryClient();
  return function Wrapper({ children }: { children: React.ReactNode }) {
    return (
      <QueryClientProvider client={testQueryClient}>
        {children}
      </QueryClientProvider>
    );
  };
}

beforeAll(() => server.listen());
afterEach(() => {
  server.resetHandlers();
  capturedUrl = null;
});
afterAll(() => server.close());

describe('useStats', () => {
  it('fetches stats without params', async () => {
    const { result } = renderHook(() => useStats(), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));

    expect(result.current.data).toEqual(mockStats);
    expect(result.current.data).toHaveLength(2);
    expect(result.current.data![0]!.modelName).toBe('gpt-4o');
    expect(result.current.data![1]!.requestCount).toBe(50);

    // Verify no query params were sent
    expect(capturedUrl!.search).toBe('');
  });

  it('with filter params passes them correctly', async () => {
    const params: StatsQueryParams = {
      providerId: 'provider-2',
      modelName: 'claude-sonnet-4-5',
      startDate: '2026-04-01',
      endDate: '2026-04-15',
    };

    const { result } = renderHook(() => useStats(params), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));

    expect(result.current.data).toEqual(mockFilteredStats);
    expect(result.current.data).toHaveLength(1);
    expect(result.current.data![0]!.modelName).toBe('claude-sonnet-4-5');

    // Verify query params were passed correctly (snake_case)
    expect(capturedUrl!.searchParams.get('provider_id')).toBe('provider-2');
    expect(capturedUrl!.searchParams.get('model_name')).toBe('claude-sonnet-4-5');
    expect(capturedUrl!.searchParams.get('start_date')).toBe('2026-04-01');
    expect(capturedUrl!.searchParams.get('end_date')).toBe('2026-04-15');
  });

  it('with partial filter params only sends provided params', async () => {
    const params: StatsQueryParams = {
      providerId: 'provider-1',
    };

    const { result } = renderHook(() => useStats(params), {
      wrapper: createWrapper(),
    });

    await waitFor(() => expect(result.current.isSuccess).toBe(true));

    // Verify only provider_id was sent
    expect(capturedUrl!.searchParams.get('provider_id')).toBe('provider-1');
    expect(capturedUrl!.searchParams.get('model_name')).toBeNull();
    expect(capturedUrl!.searchParams.get('start_date')).toBeNull();
    expect(capturedUrl!.searchParams.get('end_date')).toBeNull();
  });
});
