import time
import threading
from typing import Dict, Any, Optional, Callable, Tuple

class StatsVersionManager:
    """属性版本管理器，用于追踪影响属性计算的变更"""
    
    def __init__(self):
        self._versions: Dict[str, int] = {}
        self._lock = threading.RLock()
    
    def get_version(self, player_name: str) -> int:
        with self._lock:
            return self._versions.get(player_name, 0)
    
    def invalidate(self, player_name: str):
        with self._lock:
            self._versions[player_name] = self._versions.get(player_name, 0) + 1
    
    def remove(self, player_name: str):
        with self._lock:
            self._versions.pop(player_name, None)
    
    def validate(self, player_name: str, cached_version: int) -> bool:
        return self.get_version(player_name) == cached_version


class EnhancedStatsCache:
    """
    增强的属性计算结果缓存。
    为每个玩家分别缓存 player 和 hero 的最终属性，避免重复计算。
    """
    
    def __init__(self):
        self._player_cache: Dict[str, Tuple[int, Dict]] = {}
        self._hero_cache: Dict[str, Tuple[int, Dict]] = {}
        self._lock = threading.RLock()
    
    def get_player_stats(self, player_name: str, version: int, compute_func: Callable[[], Dict]) -> Dict:
        """
        获取玩家属性，若缓存版本匹配则直接返回，否则调用 compute_func 计算并缓存。
        """
        with self._lock:
            cached_version, cached_stats = self._player_cache.get(player_name, (0, None))
            if cached_version == version and cached_stats is not None:
                return cached_stats
            stats = compute_func()
            self._player_cache[player_name] = (version, stats)
            return stats
    
    def get_hero_stats(self, player_name: str, version: int, compute_func: Callable[[], Dict]) -> Dict:
        with self._lock:
            cached_version, cached_stats = self._hero_cache.get(player_name, (0, None))
            if cached_version == version and cached_stats is not None:
                return cached_stats
            stats = compute_func()
            self._hero_cache[player_name] = (version, stats)
            return stats
    
    def invalidate_player(self, player_name: str):
        with self._lock:
            self._player_cache.pop(player_name, None)
            self._hero_cache.pop(player_name, None)


# 全局实例
stats_version_manager = StatsVersionManager()
enhanced_stats_cache = EnhancedStatsCache()