"""Tests for Redis cache backend (mocked)."""
import json
import pytest
from unittest.mock import AsyncMock

from logos_adk.cache import CacheEntry
from logos_adk.cache.redis import RedisCacheBackend
from logos_adk.types import Response, Usage


def _make_response(content="hello"):
    return Response(content=content, tool_calls=[], usage=Usage(10, 5), raw={})


def _make_backend_with_mock():
    backend = RedisCacheBackend.__new__(RedisCacheBackend)
    backend._client = AsyncMock()
    backend._prefix = "logos:"
    backend._url = "redis://localhost:6379"
    return backend


class TestRedisCacheBackend:
    @pytest.mark.asyncio
    async def test_put_and_get(self):
        backend = _make_backend_with_mock()
        entry = CacheEntry.from_response(_make_response("redis cached"))
        entry_json = json.dumps({
            "response_data": entry.response_data,
            "created_at": entry.created_at,
            "hit_count": 0,
            "vector": None,
            "scope": None,
        })
        backend._client.get = AsyncMock(return_value=entry_json.encode())
        backend._client.set = AsyncMock()

        await backend.put("key1", entry, ttl=3600)
        backend._client.set.assert_called_once()

        result = await backend.get("key1")
        assert result is not None
        assert result.response_data["content"] == "redis cached"

    @pytest.mark.asyncio
    async def test_get_missing(self):
        backend = _make_backend_with_mock()
        backend._client.get = AsyncMock(return_value=None)
        assert await backend.get("missing") is None

    @pytest.mark.asyncio
    async def test_invalidate(self):
        backend = _make_backend_with_mock()
        backend._client.delete = AsyncMock()
        await backend.invalidate("key1")
        backend._client.delete.assert_called_once()

    @pytest.mark.asyncio
    async def test_clear(self):
        backend = _make_backend_with_mock()
        backend._client.scan = AsyncMock(return_value=(0, [b"logos:k1", b"logos:k2"]))
        backend._client.delete = AsyncMock()
        await backend.clear()
        backend._client.delete.assert_called()

    def test_constructor_stores_url(self):
        backend = RedisCacheBackend(url="redis://custom:1234")
        assert backend._url == "redis://custom:1234"
        assert backend._client is None
