"""Tests for Redis cache."""

import pytest
from unittest.mock import Mock, patch, AsyncMock


class TestRedisCache:
    """Tests for RedisCache class."""
    
    @patch('src.data.redis_cache.get_redis_client')
    @pytest.mark.asyncio
    async def test_get_ticker_cache_hit(self, mock_get_client):
        """Test getting cached ticker data."""
        mock_redis = Mock()
        mock_client = AsyncMock()
        mock_client.get.return_value = '{"price": 45000.0, "symbol": "BTC/USD"}'
        mock_redis.get_client.return_value = mock_client
        mock_get_client.return_value = mock_redis
        
        from src.data.redis_cache import RedisCache
        cache = RedisCache()
        
        result = await cache.get_ticker("BTC/USD")
        
        assert result is not None
        assert result["price"] == 45000.0
        mock_client.get.assert_called_once()
    
    @patch('src.data.redis_cache.get_redis_client')
    @pytest.mark.asyncio
    async def test_get_ticker_cache_miss(self, mock_get_client):
        """Test ticker cache miss."""
        mock_redis = Mock()
        mock_client = AsyncMock()
        mock_client.get.return_value = None
        mock_redis.get_client.return_value = mock_client
        mock_get_client.return_value = mock_redis
        
        from src.data.redis_cache import RedisCache
        cache = RedisCache()
        
        result = await cache.get_ticker("BTC/USD")
        
        assert result is None
    
    @patch('src.data.redis_cache.get_redis_client')
    @pytest.mark.asyncio
    async def test_set_ticker(self, mock_get_client):
        """Test setting ticker cache."""
        mock_redis = Mock()
        mock_client = AsyncMock()
        mock_redis.get_client.return_value = mock_client
        mock_get_client.return_value = mock_redis
        
        from src.data.redis_cache import RedisCache
        cache = RedisCache()
        
        result = await cache.set_ticker("BTC/USD", {"price": 45000.0})
        
        assert result is True
        mock_client.setex.assert_called_once()
    
    @patch('src.data.redis_cache.get_redis_client')
    @pytest.mark.asyncio
    async def test_get_ohlcv(self, mock_get_client):
        """Test getting cached OHLCV data."""
        mock_redis = Mock()
        mock_client = AsyncMock()
        mock_client.get.return_value = '[[1700000000, 45000, 45500, 44500, 45200, 1000]]'
        mock_redis.get_client.return_value = mock_client
        mock_get_client.return_value = mock_redis
        
        from src.data.redis_cache import RedisCache
        cache = RedisCache()
        
        result = await cache.get_ohlcv("BTC/USD", "1h", 100)
        
        assert result is not None
        assert len(result) == 1
        assert result[0][0] == 1700000000
    
    @patch('src.data.redis_cache.get_redis_client')
    @pytest.mark.asyncio
    async def test_set_ohlcv(self, mock_get_client):
        """Test setting OHLCV cache."""
        mock_redis = Mock()
        mock_client = AsyncMock()
        mock_redis.get_client.return_value = mock_client
        mock_get_client.return_value = mock_redis
        
        from src.data.redis_cache import RedisCache
        cache = RedisCache()
        
        ohlcv_data = [[1700000000, 45000, 45500, 44500, 45200, 1000]]
        result = await cache.set_ohlcv("BTC/USD", "1h", ohlcv_data)
        
        assert result is True
        mock_client.setex.assert_called_once()


class TestGetRedisCache:
    """Tests for get_redis_cache singleton."""
    
    @patch('src.data.redis_cache.get_redis_client')
    def test_returns_singleton(self, mock_get_client):
        """Test that get_redis_cache returns same instance."""
        mock_get_client.return_value = Mock()
        
        # Reset the global
        import src.data.redis_cache as cache_module
        cache_module._redis_cache = None
        
        from src.data.redis_cache import get_redis_cache
        
        cache1 = get_redis_cache()
        cache2 = get_redis_cache()
        
        assert cache1 is cache2
