# -*- coding: utf-8 -*-
"""基础设施层 · Redis 异步封装（缓存 / 限流 / 分布式锁）。"""
from __future__ import annotations

import asyncio
from typing import Any, Optional

from redis.asyncio import Redis

from .. import config


class Cache:
    """redis.asyncio 封装：连接池 / get / set / incr / 分布式锁（SET NX EX）。"""

    def __init__(self, url: str | None = None) -> None:
        self._redis: Optional[Redis] = None
        self._url = url or config.REDIS_URL

    async def connect(self) -> None:
        if self._redis is None:
            self._redis = Redis.from_url(self._url, decode_responses=True)

    async def close(self) -> None:
        if self._redis is not None:
            await self._redis.aclose()
            self._redis = None

    async def get(self, key: str) -> str | None:
        if self._redis is None:
            return None
        return await self._redis.get(key)

    async def set(self, key: str, value: str, ttl: int | None = None) -> None:
        if self._redis is None:
            return
        await self._redis.set(key, value, ex=ttl)

    async def delete(self, key: str) -> None:
        if self._redis is None:
            return
        await self._redis.delete(key)

    async def incr(self, key: str) -> int:
        if self._redis is None:
            return 0
        return int(await self._redis.incr(key))

    async def lock(self, key: str, ttl: int = 30) -> bool:
        """分布式锁：SET key token NX EX ttl（成功拿到锁返回 True）。"""
        if self._redis is None:
            return True  # 无 Redis 时降级为总是通过（单机部署）
        token = f"{asyncio.get_event_loop().time()}"
        ok = await self._redis.set(key, token, nx=True, ex=ttl)
        return bool(ok)

    async def unlock(self, key: str) -> None:
        if self._redis is None:
            return
        await self._redis.delete(key)
