"""
Redis wrapper for demo session service using shared Redis implementation
Provides a compatibility layer for session-specific operations
"""

import json
import structlog
from typing import Optional, Any
from shared.redis_utils import get_redis_client

logger = structlog.get_logger()


class DemoRedisWrapper:
    """Wrapper around shared Redis client for demo session operations"""

    def __init__(self, key_prefix: str = "demo_session"):
        self.key_prefix = key_prefix

    async def get_client(self):
        """Get the underlying Redis client"""
        return await get_redis_client()

    def _make_key(self, *parts: str) -> str:
        """Create Redis key with prefix"""
        return f"{self.key_prefix}:{':'.join(parts)}"

    async def set_session_data(self, session_id: str, key: str, data: Any, ttl: int = None):
        """Store session data in Redis"""
        client = await get_redis_client()
        redis_key = self._make_key(session_id, key)
        serialized = json.dumps(data) if not isinstance(data, str) else data

        if ttl:
            await client.setex(redis_key, ttl, serialized)
        else:
            await client.set(redis_key, serialized)

        logger.debug("Session data stored", session_id=session_id, key=key)

    async def get_session_data(self, session_id: str, key: str) -> Optional[Any]:
        """Retrieve session data from Redis"""
        client = await get_redis_client()
        redis_key = self._make_key(session_id, key)
        data = await client.get(redis_key)

        if data:
            try:
                return json.loads(data)
            except json.JSONDecodeError:
                return data

        return None

    async def delete_session_data(self, session_id: str, key: str = None):
        """Delete session data"""
        client = await get_redis_client()

        if key:
            redis_key = self._make_key(session_id, key)
            await client.delete(redis_key)
        else:
            pattern = self._make_key(session_id, "*")
            keys = await client.keys(pattern)
            if keys:
                await client.delete(*keys)

        logger.debug("Session data deleted", session_id=session_id, key=key)

    async def extend_session_ttl(self, session_id: str, ttl: int):
        """Extend TTL for all session keys"""
        client = await get_redis_client()
        pattern = self._make_key(session_id, "*")
        keys = await client.keys(pattern)

        for key in keys:
            await client.expire(key, ttl)

        logger.debug("Session TTL extended", session_id=session_id, ttl=ttl)

    async def set_hash(self, session_id: str, hash_key: str, field: str, value: Any):
        """Store hash field in Redis"""
        client = await get_redis_client()
        redis_key = self._make_key(session_id, hash_key)
        serialized = json.dumps(value) if not isinstance(value, str) else value
        await client.hset(redis_key, field, serialized)

    async def get_hash(self, session_id: str, hash_key: str, field: str) -> Optional[Any]:
        """Get hash field from Redis"""
        client = await get_redis_client()
        redis_key = self._make_key(session_id, hash_key)
        data = await client.hget(redis_key, field)

        if data:
            try:
                return json.loads(data)
            except json.JSONDecodeError:
                return data

        return None

    async def get_all_hash(self, session_id: str, hash_key: str) -> dict:
        """Get all hash fields"""
        client = await get_redis_client()
        redis_key = self._make_key(session_id, hash_key)
        data = await client.hgetall(redis_key)

        result = {}
        for field, value in data.items():
            try:
                result[field] = json.loads(value)
            except json.JSONDecodeError:
                result[field] = value

        return result

    async def get_client(self):
        """Get raw Redis client for direct operations"""
        return await get_redis_client()


# Cached instance
_redis_wrapper = None


async def get_redis() -> DemoRedisWrapper:
    """Dependency for FastAPI - returns wrapper around shared Redis"""
    global _redis_wrapper
    if _redis_wrapper is None:
        _redis_wrapper = DemoRedisWrapper()
    return _redis_wrapper
