import { describe, it, expect, vi, beforeEach } from 'vitest'
import { marketDataApi } from '../marketData'
import { apiClient } from '../client'

vi.mock('../client')

describe('marketDataApi', () => {
    beforeEach(() => {
        vi.clearAllMocks()
    })

    describe('getOHLCV', () => {
        it('calls correct endpoint with symbol', async () => {
            const mockData = [{ time: 1234567890, open: 100, high: 105, low: 95, close: 102, volume: 1000 }]
            vi.mocked(apiClient.get).mockResolvedValue({ data: mockData })

            const result = await marketDataApi.getOHLCV('BTC/USD')

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/ohlcv/BTC/USD', {
                params: { timeframe: '1h' },
            })
            expect(result).toEqual(mockData)
        })

        it('passes custom timeframe', async () => {
            vi.mocked(apiClient.get).mockResolvedValue({ data: [] })

            await marketDataApi.getOHLCV('ETH/USD', '4h')

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/ohlcv/ETH/USD', {
                params: { timeframe: '4h' },
            })
        })
    })

    describe('getTicker', () => {
        it('calls correct endpoint', async () => {
            const mockTicker = {
                symbol: 'BTC/USD',
                bid: 41000,
                ask: 41050,
                last: 41025,
                high: 42000,
                low: 40000,
                volume: 5000,
                timestamp: 1234567890,
                provider: 'CoinGecko',
            }
            vi.mocked(apiClient.get).mockResolvedValue({ data: mockTicker })

            const result = await marketDataApi.getTicker('BTC/USD')

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/ticker/BTC/USD')
            expect(result).toEqual(mockTicker)
        })
    })

    describe('getProviderHealth', () => {
        it('calls correct endpoint without provider param', async () => {
            const mockHealth = { active_provider: 'CoinGecko', health: {} }
            vi.mocked(apiClient.get).mockResolvedValue({ data: mockHealth })

            const result = await marketDataApi.getProviderHealth()

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/providers/health', { params: {} })
            expect(result).toEqual(mockHealth)
        })

        it('passes provider param when specified', async () => {
            vi.mocked(apiClient.get).mockResolvedValue({ data: {} })

            await marketDataApi.getProviderHealth('CCXT')

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/providers/health', {
                params: { provider: 'CCXT' },
            })
        })
    })

    describe('getProviderStatus', () => {
        it('calls correct endpoint', async () => {
            const mockStatus = {
                active_provider: 'CoinGecko',
                providers: {},
                cache: { size: 10, max_size: 100 },
            }
            vi.mocked(apiClient.get).mockResolvedValue({ data: mockStatus })

            const result = await marketDataApi.getProviderStatus()

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/providers/status')
            expect(result).toEqual(mockStatus)
        })
    })

    describe('getProviderConfig', () => {
        it('calls correct endpoint', async () => {
            const mockConfig = {
                primary: [{ name: 'CoinGecko', enabled: true, priority: 1 }],
                fallback: { name: 'CCXT', enabled: true },
                caching: { ticker_ttl: 60, ohlcv_ttl: 300, max_cache_size: 1000 },
                websocket: { enabled: true, reconnect_interval: 5000, ping_interval: 30000 },
            }
            vi.mocked(apiClient.get).mockResolvedValue({ data: mockConfig })

            const result = await marketDataApi.getProviderConfig()

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/providers/config')
            expect(result).toEqual(mockConfig)
        })
    })

    describe('updateProviderConfig', () => {
        it('calls correct endpoint with config updates', async () => {
            const updates = { caching: { ticker_ttl: 120 } }
            const mockResponse = { message: 'Updated', config: {} }
            vi.mocked(apiClient.put).mockResolvedValue({ data: mockResponse })

            const result = await marketDataApi.updateProviderConfig(updates as any)

            expect(apiClient.put).toHaveBeenCalledWith('/api/market-data/providers/config', updates)
            expect(result).toEqual(mockResponse)
        })
    })

    describe('getSpreadData', () => {
        it('calls correct endpoint with all parameters', async () => {
            const mockResponse = {
                primarySymbol: 'BTC/USD',
                secondarySymbol: 'ETH/USD',
                timeframe: '1h',
                lookbackWindow: 50,
                data: [],
                currentSpread: 0.5,
                currentZScore: 1.2,
            }
            vi.mocked(apiClient.get).mockResolvedValue({ data: mockResponse })

            const result = await marketDataApi.getSpreadData('BTC/USD', 'ETH/USD', '4h', 100)

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/spread', {
                params: {
                    primary_symbol: 'BTC/USD',
                    secondary_symbol: 'ETH/USD',
                    timeframe: '4h',
                    lookback: 100,
                },
            })
            expect(result).toEqual(mockResponse)
        })

        it('uses default values for optional parameters', async () => {
            vi.mocked(apiClient.get).mockResolvedValue({ data: {} })

            await marketDataApi.getSpreadData('BTC/USD', 'ETH/USD')

            expect(apiClient.get).toHaveBeenCalledWith('/api/market-data/spread', {
                params: {
                    primary_symbol: 'BTC/USD',
                    secondary_symbol: 'ETH/USD',
                    timeframe: '1h',
                    lookback: 50,
                },
            })
        })
    })
})
