"""
缓存测试
"""
import pytest
from redis import Redis
from datetime import datetime

from fastapi_tortoise_crud.cache import (
    CacheManager,
    cache,
    invalidate_cache,
    JsonEncoder
)


@pytest.fixture
def redis_client():
    """Redis客户端"""
    return Redis(host='localhost', port=6379, db=0)


@pytest.fixture
def cache_manager(redis_client):
    """缓存管理器"""
    return CacheManager(redis_client)


def test_json_encoder():
    """测试JSON编码器"""
    # 测试datetime编码
    now = datetime.now()
    encoder = JsonEncoder()
    encoded = encoder.default(now)
    assert isinstance(encoded, str)
    assert encoded == now.isoformat()


@pytest.mark.asyncio
async def test_cache_manager(cache_manager):
    """测试缓存管理器"""
    # 测试设置缓存
    key = "test_key"
    value = {"name": "test", "value": 123}
    await cache_manager.set(key, value, timeout=60)
    
    # 测试获取缓存
    cached = await cache_manager.get(key)
    assert cached == value
    
    # 测试删除缓存
    await cache_manager.delete(key)
    cached = await cache_manager.get(key)
    assert cached is None


@pytest.mark.asyncio
async def test_cache_decorator(cache_manager):
    """测试缓存装饰器"""
    call_count = 0
    
    @cache(timeout=60)
    async def test_func(param):
        nonlocal call_count
        call_count += 1
        return {"param": param, "count": call_count}
    
    # 第一次调用，应该执行函数
    result1 = await test_func("test")
    assert result1["count"] == 1
    
    # 第二次调用，应该从缓存获取
    result2 = await test_func("test")
    assert result2["count"] == 1  # count没有增加，说明使用了缓存
    assert result2 == result1


@pytest.mark.asyncio
async def test_invalidate_cache(cache_manager):
    """测试缓存失效装饰器"""
    # 设置一些测试缓存
    await cache_manager.set("test:1", "value1")
    await cache_manager.set("test:2", "value2")
    
    @invalidate_cache(key_pattern="test:*")
    async def clear_cache():
        return "cleared"
    
    # 执行函数，应该清除所有test:*的缓存
    await clear_cache()
    
    # 验证缓存已被清除
    assert await cache_manager.get("test:1") is None
    assert await cache_manager.get("test:2") is None


@pytest.mark.asyncio
async def test_cache_with_custom_key(cache_manager):
    """测试使用自定义键的缓存"""
    def key_builder(*args, **kwargs):
        return f"custom:{args[0]}:{kwargs.get('type', 'default')}"
    
    @cache(key_builder=key_builder)
    async def test_func(name, type="default"):
        return {"name": name, "type": type}
    
    # 使用不同参数调用
    result1 = await test_func("test", type="type1")
    result2 = await test_func("test", type="type2")
    
    # 验证缓存是否正确存储
    cached1 = await cache_manager.get("custom:test:type1")
    cached2 = await cache_manager.get("custom:test:type2")
    
    assert cached1 == result1
    assert cached2 == result2


@pytest.mark.asyncio
async def test_cache_clear_pattern(cache_manager):
    """测试按模式清除缓存"""
    # 设置不同模式的缓存
    await cache_manager.set("test:1", "value1")
    await cache_manager.set("test:2", "value2")
    await cache_manager.set("other:1", "value3")
    
    # 清除特定模式的缓存
    await cache_manager.clear("test:*")
    
    # 验证清除结果
    assert await cache_manager.get("test:1") is None
    assert await cache_manager.get("test:2") is None
    assert await cache_manager.get("other:1") is not None  # 不应被清除 