"""Unit tests for pricing service."""

import pytest
from unittest.mock import Mock, patch, MagicMock
from decimal import Decimal

from src.data.pricing_service import PricingService, get_pricing_service
from src.data.providers.base_provider import BasePricingProvider


class MockProvider(BasePricingProvider):
    """Mock provider for testing."""
    
    @property
    def name(self) -> str:
        return "MockProvider"
    
    @property
    def supports_websocket(self) -> bool:
        return False
    
    def connect(self) -> bool:
        self._connected = True
        return True
    
    def disconnect(self):
        self._connected = False
    
    def get_ticker(self, symbol: str):
        return {
            'symbol': symbol,
            'bid': Decimal('50000'),
            'ask': Decimal('50001'),
            'last': Decimal('50000.5'),
            'high': Decimal('51000'),
            'low': Decimal('49000'),
            'volume': Decimal('1000000'),
            'timestamp': 1609459200000,
        }
    
    def get_ohlcv(self, symbol: str, timeframe: str = '1h', since=None, limit: int = 100):
        return [[1609459200000, 50000, 51000, 49000, 50000, 1000]]
    
    def subscribe_ticker(self, symbol: str, callback) -> bool:
        if symbol not in self._subscribers:
            self._subscribers[symbol] = []
        self._subscribers[symbol].append(callback)
        return True


@pytest.fixture
def mock_config():
    """Create a mock configuration."""
    config = Mock()
    config.get = Mock(side_effect=lambda key, default=None: {
        "data_providers.primary": [
            {"name": "mock", "enabled": True, "priority": 1}
        ],
        "data_providers.fallback": {"enabled": True, "api_key": ""},
        "data_providers.caching.ticker_ttl": 2,
        "data_providers.caching.ohlcv_ttl": 60,
        "data_providers.caching.max_cache_size": 1000,
    }.get(key, default))
    return config


class TestPricingService:
    """Tests for PricingService."""
    
    @patch('src.data.pricing_service.get_config')
    @patch('src.data.providers.ccxt_provider.CCXTProvider')
    @patch('src.data.providers.coingecko_provider.CoinGeckoProvider')
    def test_init(self, mock_coingecko, mock_ccxt, mock_get_config, mock_config):
        """Test service initialization."""
        mock_get_config.return_value = mock_config
        mock_ccxt_instance = MockProvider()
        mock_ccxt.return_value = mock_ccxt_instance
        mock_coingecko_instance = MockProvider()
        mock_coingecko.return_value = mock_coingecko_instance
        
        service = PricingService()
        
        assert service.cache is not None
        assert service.health_monitor is not None
    
    @patch('src.data.pricing_service.get_config')
    @patch('src.data.providers.ccxt_provider.CCXTProvider')
    def test_get_ticker(self, mock_ccxt, mock_get_config, mock_config):
        """Test getting ticker data."""
        mock_get_config.return_value = mock_config
        mock_provider = MockProvider()
        mock_ccxt.return_value = mock_provider
        
        service = PricingService()
        service._providers["MockProvider"] = mock_provider
        service._active_provider = "MockProvider"
        
        ticker = service.get_ticker("BTC/USD")
        
        assert ticker['symbol'] == "BTC/USD"
        assert isinstance(ticker['last'], Decimal)
    
    @patch('src.data.pricing_service.get_config')
    @patch('src.data.providers.ccxt_provider.CCXTProvider')
    def test_get_ohlcv(self, mock_ccxt, mock_get_config, mock_config):
        """Test getting OHLCV data."""
        mock_get_config.return_value = mock_config
        mock_provider = MockProvider()
        mock_ccxt.return_value = mock_provider
        
        service = PricingService()
        service._providers["MockProvider"] = mock_provider
        service._active_provider = "MockProvider"
        
        ohlcv = service.get_ohlcv("BTC/USD", "1h", limit=10)
        
        assert len(ohlcv) > 0
        assert len(ohlcv[0]) == 6
    
    @patch('src.data.pricing_service.get_config')
    @patch('src.data.providers.ccxt_provider.CCXTProvider')
    def test_subscribe_ticker(self, mock_ccxt, mock_get_config, mock_config):
        """Test subscribing to ticker updates."""
        mock_get_config.return_value = mock_config
        mock_provider = MockProvider()
        mock_ccxt.return_value = mock_provider
        
        service = PricingService()
        service._providers["MockProvider"] = mock_provider
        service._active_provider = "MockProvider"
        
        callback = Mock()
        result = service.subscribe_ticker("BTC/USD", callback)
        
        assert result is True
