"""Redis 缓存工具类 — 管理会计OS"""
import json
import hashlib
import logging
from typing import Any, Optional

logger = logging.getLogger("cma.cache")

try:
    import redis as redis_lib
    _client = redis_lib.Redis(
        host="127.0.0.1",
        port=6379,
        db=1,
        decode_responses=True,
        socket_connect_timeout=2,
        socket_timeout=3,
    )
    _client.ping()
    _available = True
    logger.info("Redis 缓存已连接 (db=1)")
except Exception as e:
    _client = None
    _available = False
    logger.warning(f"Redis 不可用，回退到无缓存模式: {e}")


def _make_key(module: str, key: str) -> str:
    """生成统一格式的缓存key: cma:cache:{module}:{hash}"""
    h = hashlib.md5(key.encode()).hexdigest()[:16]
    return f"cma:cache:{module}:{h}"


def get(module: str, key: str) -> Optional[Any]:
    """获取缓存"""
    if not _available:
        return None
    try:
        full_key = _make_key(module, key)
        data = _client.get(full_key)
        if data:
            return json.loads(data)
        return None
    except Exception as e:
        logger.warning(f"缓存读取失败 [{module}]: {e}")
        return None


def set(module: str, key: str, value: Any, ttl_seconds: int = 300) -> bool:
    """写入缓存，默认5分钟"""
    if not _available:
        return False
    try:
        full_key = _make_key(module, key)
        _client.setex(full_key, ttl_seconds, json.dumps(value, ensure_ascii=False))
        return True
    except Exception as e:
        logger.warning(f"缓存写入失败 [{module}]: {e}")
        return False


def delete(module: str, key: str = None) -> bool:
    """删除缓存。不传key则清空该模块所有缓存"""
    if not _available:
        return False
    try:
        if key:
            full_key = _make_key(module, key)
            _client.delete(full_key)
        else:
            pattern = f"cma:cache:{module}:*"
            cursor = 0
            while True:
                cursor, keys = _client.scan(cursor=cursor, match=pattern, count=100)
                if keys:
                    _client.delete(*keys)
                if cursor == 0:
                    break
        return True
    except Exception as e:
        logger.warning(f"缓存删除失败 [{module}]: {e}")
        return False


def clear_all() -> bool:
    """清空所有CMA缓存"""
    if not _available:
        return False
    try:
        cursor = 0
        while True:
            cursor, keys = _client.scan(cursor=cursor, match="cma:cache:*", count=200)
            if keys:
                _client.delete(*keys)
            if cursor == 0:
                break
        return True
    except Exception as e:
        logger.warning(f"缓存清空失败: {e}")
        return False
