import { describe, it, expect, vi, beforeEach } from 'vitest'
import { renderHook, act, waitFor } from '@testing-library/react'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { ReactNode } from 'react'
import { useProviderStatus } from '../useProviderStatus'
import * as marketDataApi from '../../api/marketData'

vi.mock('../../api/marketData')
vi.mock('../../components/WebSocketProvider', () => ({
    useWebSocketContext: () => ({
        isConnected: true,
        lastMessage: null,
        subscribe: vi.fn(),
    }),
}))

describe('useProviderStatus', () => {
    let queryClient: QueryClient

    beforeEach(() => {
        queryClient = new QueryClient({
            defaultOptions: {
                queries: { retry: false },
            },
        })
        vi.clearAllMocks()
    })

    const wrapper = ({ children }: { children: ReactNode }) => (
        <QueryClientProvider client= { queryClient } > { children } </QueryClientProvider>
  )

it('returns loading state initially', () => {
    vi.mocked(marketDataApi.marketDataApi.getProviderStatus).mockImplementation(
        () => new Promise(() => { }) // Never resolves
    )

    const { result } = renderHook(() => useProviderStatus(), { wrapper })

    expect(result.current.isLoading).toBe(true)
})

it('returns provider status after loading', async () => {
    const mockStatus = {
        primary_provider: 'CoinGecko',
        primary_healthy: true,
        fallback_provider: 'CCXT',
        fallback_healthy: true,
        last_check: '2024-01-01T00:00:00Z',
    }

    vi.mocked(marketDataApi.marketDataApi.getProviderStatus).mockResolvedValue(mockStatus)

    const { result } = renderHook(() => useProviderStatus(), { wrapper })

    await waitFor(() => {
        expect(result.current.isLoading).toBe(false)
    })

    expect(result.current.status).toEqual(mockStatus)
})

it('returns error when API call fails', async () => {
    const mockError = new Error('API Error')
    vi.mocked(marketDataApi.marketDataApi.getProviderStatus).mockRejectedValue(mockError)

    const { result } = renderHook(() => useProviderStatus(), { wrapper })

    await waitFor(() => {
        expect(result.current.error).not.toBeNull()
    })

    expect(result.current.error?.message).toBe('API Error')
})

it('provides refetch function', async () => {
    const mockStatus = {
        primary_provider: 'CoinGecko',
        primary_healthy: true,
        fallback_provider: 'CCXT',
        fallback_healthy: true,
        last_check: '2024-01-01T00:00:00Z',
    }

    vi.mocked(marketDataApi.marketDataApi.getProviderStatus).mockResolvedValue(mockStatus)

    const { result } = renderHook(() => useProviderStatus(), { wrapper })

    await waitFor(() => {
        expect(result.current.isLoading).toBe(false)
    })

    expect(result.current.refetch).toBeDefined()
    expect(typeof result.current.refetch).toBe('function')
})
})
