#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
缓存管理模块
提供Redis缓存连接和操作功能
"""

import logging
import json
from typing import Any, Optional, Union, Dict, List
import redis

from config.database_config import CacheConfig
from utils.logger import get_logger

# 获取日志记录器
logger = get_logger("data.cache")


class RedisClient:
    """Redis客户端，封装常用的Redis操作"""
    
    _instance = None
    _redis_client = None
    
    def __new__(cls, *args, **kwargs):
        """单例模式，确保只有一个Redis连接"""
        if cls._instance is None:
            cls._instance = super(RedisClient, cls).__new__(cls)
        return cls._instance
    
    def __init__(self):
        """初始化Redis连接"""
        if self._redis_client is None:
            try:
                self._redis_client = redis.Redis(
                    **CacheConfig.get_redis_connection_args()
                )
                logger.info(f"Redis连接已建立：{CacheConfig.REDIS_HOST}:{CacheConfig.REDIS_PORT}/{CacheConfig.REDIS_DB}")
            except Exception as e:
                logger.error(f"Redis连接失败：{str(e)}")
                self._redis_client = None
    
    def get_client(self) -> redis.Redis:
        """获取Redis客户端"""
        return self._redis_client
    
    def add_prefix(self, key: str) -> str:
        """添加键前缀"""
        return f"{CacheConfig.REDIS_PREFIX}{key}"
    
    def set(self, key: str, value: Any, expire: Optional[int] = None) -> bool:
        """
        设置缓存
        
        Args:
            key: 缓存键
            value: 缓存值，如果不是字符串会尝试JSON序列化
            expire: 过期时间(秒)
            
        Returns:
            bool: 操作是否成功
        """
        try:
            if self._redis_client is None:
                return False
                
            # 添加前缀
            prefixed_key = self.add_prefix(key)
            
            # 处理非字符串值
            if not isinstance(value, (str, bytes, int, float)):
                value = json.dumps(value, ensure_ascii=False)
            
            # 设置缓存
            self._redis_client.set(prefixed_key, value)
            
            # 设置过期时间
            if expire is not None:
                self._redis_client.expire(prefixed_key, expire)
                
            return True
        except Exception as e:
            logger.error(f"设置缓存失败：{str(e)}")
            return False
    
    def get(self, key: str, default: Any = None) -> Any:
        """
        获取缓存
        
        Args:
            key: 缓存键
            default: 默认值（缓存不存在时返回）
            
        Returns:
            Any: 缓存值或默认值
        """
        try:
            if self._redis_client is None:
                return default
                
            # 添加前缀
            prefixed_key = self.add_prefix(key)
            
            # 获取缓存
            value = self._redis_client.get(prefixed_key)
            
            if value is None:
                return default
                
            # 尝试JSON反序列化
            try:
                return json.loads(value)
            except (TypeError, json.JSONDecodeError):
                return value
        except Exception as e:
            logger.error(f"获取缓存失败：{str(e)}")
            return default
    
    def delete(self, key: str) -> bool:
        """
        删除缓存
        
        Args:
            key: 缓存键
            
        Returns:
            bool: 操作是否成功
        """
        try:
            if self._redis_client is None:
                return False
                
            # 添加前缀
            prefixed_key = self.add_prefix(key)
            
            # 删除缓存
            return bool(self._redis_client.delete(prefixed_key))
        except Exception as e:
            logger.error(f"删除缓存失败：{str(e)}")
            return False
    
    def exists(self, key: str) -> bool:
        """
        检查缓存是否存在
        
        Args:
            key: 缓存键
            
        Returns:
            bool: 缓存是否存在
        """
        try:
            if self._redis_client is None:
                return False
                
            # 添加前缀
            prefixed_key = self.add_prefix(key)
            
            # 检查缓存
            return bool(self._redis_client.exists(prefixed_key))
        except Exception as e:
            logger.error(f"检查缓存失败：{str(e)}")
            return False
    
    def expire(self, key: str, seconds: int) -> bool:
        """
        设置缓存过期时间
        
        Args:
            key: 缓存键
            seconds: 过期时间(秒)
            
        Returns:
            bool: 操作是否成功
        """
        try:
            if self._redis_client is None:
                return False
                
            # 添加前缀
            prefixed_key = self.add_prefix(key)
            
            # 设置过期时间
            return bool(self._redis_client.expire(prefixed_key, seconds))
        except Exception as e:
            logger.error(f"设置缓存过期时间失败：{str(e)}")
            return False
    
    def ttl(self, key: str) -> int:
        """
        获取缓存剩余过期时间
        
        Args:
            key: 缓存键
            
        Returns:
            int: 剩余过期时间(秒)，-1表示永不过期，-2表示键不存在
        """
        try:
            if self._redis_client is None:
                return -2
                
            # 添加前缀
            prefixed_key = self.add_prefix(key)
            
            # 获取过期时间
            return self._redis_client.ttl(prefixed_key)
        except Exception as e:
            logger.error(f"获取缓存过期时间失败：{str(e)}")
            return -2
    
    def hset(self, key: str, field: str, value: Any) -> bool:
        """
        设置哈希表字段
        
        Args:
            key: 缓存键
            field: 字段名
            value: 字段值
            
        Returns:
            bool: 操作是否成功
        """
        try:
            if self._redis_client is None:
                return False
                
            # 添加前缀
            prefixed_key = self.add_prefix(key)
            
            # 处理非字符串值
            if not isinstance(value, (str, bytes, int, float)):
                value = json.dumps(value, ensure_ascii=False)
            
            # 设置哈希表字段
            self._redis_client.hset(prefixed_key, field, value)
            return True
        except Exception as e:
            logger.error(f"设置哈希表字段失败：{str(e)}")
            return False
    
    def hget(self, key: str, field: str, default: Any = None) -> Any:
        """
        获取哈希表字段
        
        Args:
            key: 缓存键
            field: 字段名
            default: 默认值（字段不存在时返回）
            
        Returns:
            Any: 字段值或默认值
        """
        try:
            if self._redis_client is None:
                return default
                
            # 添加前缀
            prefixed_key = self.add_prefix(key)
            
            # 获取哈希表字段
            value = self._redis_client.hget(prefixed_key, field)
            
            if value is None:
                return default
                
            # 尝试JSON反序列化
            try:
                return json.loads(value)
            except (TypeError, json.JSONDecodeError):
                return value
        except Exception as e:
            logger.error(f"获取哈希表字段失败：{str(e)}")
            return default


# 导出Redis客户端单例
redis_client = RedisClient()


def get_cache():
    """获取Redis客户端"""
    return redis_client 