"""Real client implementations for production use.

These clients wrap actual services (httpx, Redis) while implementing
the same interface as their mock counterparts in mocks.py.
"""

from dataclasses import dataclass
from typing import TYPE_CHECKING, Any

import httpx

if TYPE_CHECKING:
    import redis.asyncio as aioredis


@dataclass
class HttpxHttpClient:
    """Real HTTP client using httpx.

    Returns httpx.Response which matches MockHttpResponse interface:
    - .status_code
    - .json() method
    - .content (bytes)
    - .text (str)

    Example:
        ```python
        async with httpx.AsyncClient() as raw_client:
            client = HttpxHttpClient(raw_client)
            response = await client.get("https://api.example.com/data")
            data = response.json()
        ```
    """

    _client: httpx.AsyncClient

    async def get(self, url: str, **kwargs: Any) -> httpx.Response:
        """Make a GET request.

        Args:
            url: The URL to request.
            **kwargs: Additional arguments passed to httpx (params, headers, etc.)

        Returns:
            httpx.Response with .status_code, .json(), .content, .text
        """
        return await self._client.get(url, **kwargs)

    async def post(self, url: str, **kwargs: Any) -> httpx.Response:
        """Make a POST request.

        Args:
            url: The URL to request.
            **kwargs: Additional arguments passed to httpx (json, data, headers, etc.)

        Returns:
            httpx.Response with .status_code, .json(), .content, .text
        """
        return await self._client.post(url, **kwargs)


@dataclass
class RedisCacheClient:
    """Real cache client using Redis.

    Implements the CacheClient protocol from base.py:
    - get(key) -> str | None
    - set(key, value, ttl) -> None
    - delete(key) -> None

    Example:
        ```python
        import redis.asyncio as aioredis
        redis = aioredis.from_url("redis://localhost:6379")
        cache = RedisCacheClient(redis)
        await cache.set("user:123", "data", ttl=3600)
        ```
    """

    _redis: "aioredis.Redis"

    async def get(self, key: str) -> str | None:
        """Get a value from the cache.

        Args:
            key: The cache key.

        Returns:
            The cached value, or None if not found.
        """
        return await self._redis.get(key)

    async def set(self, key: str, value: str, ttl: int | None = None) -> None:
        """Set a value in the cache.

        Args:
            key: The cache key.
            value: The value to cache.
            ttl: Time-to-live in seconds. None for no expiry.
        """
        await self._redis.set(key, value, ex=ttl)

    async def delete(self, key: str) -> None:
        """Delete a value from the cache.

        Args:
            key: The cache key to delete.
        """
        await self._redis.delete(key)
