"""Redis client and caching layer."""
import json
import logging
from typing import Any, Optional

import redis.asyncio as aioredis
from app.core.settings import get_settings

logger = logging.getLogger(__name__)

settings = get_settings()

# Redis client instance
redis_client: Optional[aioredis.Redis] = None


async def get_redis() -> aioredis.Redis:
    """Get Redis client instance."""
    global redis_client
    if redis_client is None:
        try:
            redis_client = aioredis.from_url(
                settings.REDIS_URL,
                decode_responses=True,
                socket_connect_timeout=10,
                socket_timeout=10,
            )
            await redis_client.ping()
            logger.info("Connected to Redis")
        except Exception as e:
            logger.warning(f"Failed to connect to Redis: {e}")
            redis_client = None
    return redis_client


async def close_redis():
    """Close Redis connection."""
    global redis_client
    if redis_client:
        await redis_client.close()
        redis_client = None
        logger.info("Closed Redis connection")


async def cache_get(key: str) -> Optional[str]:
    """Get cached value."""
    try:
        client = await get_redis()
        if not client:
            return None
        value = await client.get(key)
        return value
    except Exception as e:
        logger.error(f"Cache get error for key {key}: {e}")
        return None


async def cache_set(key: str, value: str, ttl: int = 3600):
    """Set cached value with TTL (default 1 hour)."""
    try:
        client = await get_redis()
        if not client:
            return
        await client.set(key, value, ex=ttl)
    except Exception as e:
        logger.error(f"Cache set error for key {key}: {e}")


async def cache_delete(key: str):
    """Delete cached value."""
    try:
        client = await get_redis()
        if not client:
            return
        await client.delete(key)
    except Exception as e:
        logger.error(f"Cache delete error for key {key}: {e}")


async def cache_invalidate_pattern(pattern: str):
    """Invalidate all cached keys matching pattern."""
    try:
        client = await get_redis()
        if not client:
            return
        keys = await client.keys(pattern)
        if keys:
            await client.delete(*keys)
    except Exception as e:
        logger.error(f"Cache invalidate error for pattern {pattern}: {e}")
