"""Redis client factories.

``settings.REDIS_URL`` selects the default logical database (usually ``0``).
Token blacklist and application cache use separate logical DBs on the same
Redis instance (``REDIS_TOKEN_BLACKLIST_DB``, ``REDIS_CACHE_DB``) so keys never
collide and TTL policies can differ per workload.

Usage::

    from app.infrastructure.redis_client import get_redis, get_redis_blacklist

    get_redis().set("key", "value", ex=300)
    get_redis_blacklist().setex("blacklist:…", ttl, "1")
"""

# Enable future language features for compatibility
from __future__ import annotations

# Import logging
import logging

# Import urlparse, urlunparse from urllib.parse
from urllib.parse import urlparse, urlunparse

# Import redis
import redis

# Import settings from app.config
from app.config import settings

# Assign logger = logging.getLogger(__name__)
logger = logging.getLogger(__name__)

# Assign _clients = {}
_clients: dict[str, redis.Redis] = {}


# Define function _redis_url_with_db
def _redis_url_with_db(base_url: str, db_index: int) -> str:
    """Return *base_url* with its path replaced by ``/{db_index}``."""
    # Assign parsed = urlparse(base_url)
    parsed = urlparse(base_url)
    # Assign path = f"/{db_index}"
    path = f"/{db_index}"
    # Return urlunparse(
    return urlunparse(
        (parsed.scheme, parsed.netloc, path, "", "", ""),
    )


# Define function _get_client
def _get_client(url: str) -> redis.Redis:
    # Check: url not in _clients
    if url not in _clients:
        # Assign _clients[url] = redis.from_url(url, decode_responses=True)
        _clients[url] = redis.from_url(url, decode_responses=True)
        # Log info: "Redis client connected to %s", url
        logger.info("Redis client connected to %s", url)
    # Return _clients[url]
    return _clients[url]


# Define function get_redis
def get_redis() -> redis.Redis:
    """Default Redis connection (URL from ``settings.REDIS_URL``)."""
    # Return _get_client(settings.REDIS_URL)
    return _get_client(settings.REDIS_URL)


# Define function get_redis_blacklist
def get_redis_blacklist() -> redis.Redis:
    """Redis DB used for JWT revocation (``jti`` keys with TTL)."""
    # Assign url = _redis_url_with_db(
    url = _redis_url_with_db(
        settings.REDIS_URL,
        settings.REDIS_TOKEN_BLACKLIST_DB,
    )
    # Return _get_client(url)
    return _get_client(url)


# Define function get_redis_cache
def get_redis_cache() -> redis.Redis:
    """Redis DB reserved for shared cache (scores, queues, etc.)."""
    # Assign url = _redis_url_with_db(
    url = _redis_url_with_db(
        settings.REDIS_URL,
        settings.REDIS_CACHE_DB,
    )
    # Return _get_client(url)
    return _get_client(url)
