import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { renderHook, waitFor } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { setupServer } from 'msw/node'
import React from 'react'
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()
  })
})
