"""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")
"""

from __future__ import annotations

import logging
from urllib.parse import urlparse, urlunparse

import redis

from app.config import settings

logger = logging.getLogger(__name__)

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


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


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


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


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


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