"""性能优化插件 - 极致性能调优

提供以下优化功能:
1. 函数级 LRU 缓存装饰器
2. 对象池复用
3. 批量操作优化
4. 内存预分配
5. 热点代码路径优化
"""
import sys
import time
import functools
from typing import Any, Callable, Optional, TypeVar, Generic, Dict, List, Set
from collections import deque
from dataclasses import dataclass, field
from threading import Lock
import weakref

# ========== 类型定义 ==========
T = TypeVar('T')
F = TypeVar('F', bound=Callable)


# ========== 高性能缓存装饰器 ==========
class FastCache:
    """超高速缓存管理器
    
    特性:
    - 基于 dict 的 O(1) 查找
    - LRU 淘汰策略
    - 可选 TTL 过期
    - 统计命中率
    """
    __slots__ = ('_cache', '_order', '_maxsize', '_ttl', '_hits', '_misses', '_lock')
    
    def __init__(self, maxsize: int = 1024, ttl: float = 0):
        self._cache: Dict[Any, Any] = {}
        self._order: deque = deque()
        self._maxsize = maxsize
        self._ttl = ttl
        self._hits = 0
        self._misses = 0
        self._lock = Lock() if sys.version_info < (3, 9) else None
    
    def get(self, key: Any) -> tuple[bool, Any]:
        """获取缓存值
        
        Returns:
            (是否命中，值)
        """
        if key not in self._cache:
            self._misses += 1
            return False, None
        
        entry = self._cache[key]
        # 检查 TTL
        if self._ttl > 0 and time.time() - entry[1] > self._ttl:
            del self._cache[key]
            try:
                self._order.remove(key)
            except ValueError:
                pass
            self._misses += 1
            return False, None
        
        # 更新 LRU 顺序
        self._order.remove(key)
        self._order.append(key)
        self._hits += 1
        return True, entry[0]
    
    def set(self, key: Any, value: Any):
        """设置缓存值"""
        if key in self._cache:
            self._order.remove(key)
        elif len(self._cache) >= self._maxsize:
            # 淘汰最旧的
            oldest = self._order.popleft()
            del self._cache[oldest]
        
        self._cache[key] = (value, time.time())
        self._order.append(key)
    
    def clear(self):
        """清空缓存"""
        self._cache.clear()
        self._order.clear()
        self._hits = 0
        self._misses = 0
    
    @property
    def hit_rate(self) -> float:
        """获取命中率"""
        total = self._hits + self._misses
        return self._hits / total if total > 0 else 0.0
    
    def stats(self) -> dict[str, Any]:
        return {
            "size": len(self._cache),
            "maxsize": self._maxsize,
            "hits": self._hits,
            "misses": self._misses,
            "hit_rate": self.hit_rate,
        }


def cached(maxsize: int = 1024, ttl: float = 0, key_func: Optional[Callable] = None):
    """高性能缓存装饰器
    
    Args:
        maxsize: 最大缓存条目数
        ttl: 过期时间（秒），0 表示永不过期
        key_func: 自定义 key 生成函数，默认使用 args+kwargs
    
    Example:
        @cached(maxsize=100)
        def expensive_compute(x, y):
            return x ** y
    """
    _cache = FastCache(maxsize=maxsize, ttl=ttl)
    
    def decorator(func: F) -> F:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # 生成缓存 key
            if key_func:
                key = key_func(*args, **kwargs)
            else:
                key = (args, tuple(sorted(kwargs.items())))
            
            hit, value = _cache.get(key)
            if hit:
                return value
            
            value = func(*args, **kwargs)
            _cache.set(key, value)
            return value
        
        wrapper.cache = _cache  # type: ignore
        wrapper.cache_clear = _cache.clear  # type: ignore
        wrapper.cache_stats = _cache.stats  # type: ignore
        return wrapper  # type: ignore
    
    return decorator  # type: ignore


# ========== 对象池 ==========
class ObjectPool(Generic[T]):
    """高性能对象池
    
    特性:
    - 避免频繁创建/销毁对象
    - 线程安全（可选）
    - 自动扩容
    - 使用统计
    
    Example:
        pool = ObjectPool(lambda: bytearray(4096))
        buf = pool.acquire()
        # ... use buf ...
        pool.release(buf)
    """
    __slots__ = ('_factory', '_pool', '_maxsize', '_created', '_acquired', '_lock')
    
    def __init__(self, factory: Callable[[], T], maxsize: int = 100):
        self._factory = factory
        self._pool: List[T] = []
        self._maxsize = maxsize
        self._created = 0
        self._acquired = 0
        self._lock = Lock() if sys.version_info < (3, 9) else None
    
    def acquire(self) -> T:
        """从池中获取对象"""
        if self._pool:
            obj = self._pool.pop()
        else:
            obj = self._factory()
            self._created += 1
        self._acquired += 1
        return obj
    
    def release(self, obj: T):
        """释放对象回池"""
        if len(self._pool) < self._maxsize:
            self._pool.append(obj)
    
    def clear(self):
        """清空对象池"""
        self._pool.clear()
    
    @property
    def size(self) -> int:
        return len(self._pool)
    
    def stats(self) -> dict[str, Any]:
        return {
            "pool_size": len(self._pool),
            "maxsize": self._maxsize,
            "total_created": self._created,
            "total_acquired": self._acquired,
            "reuse_rate": (self._acquired - self._created) / self._acquired if self._acquired > 0 else 0.0,
        }


# ========== 批量处理器 ==========
class BatchProcessor(Generic[T]):
    """批量操作处理器
    
    特性:
    - 累积一定数量后批量处理
    - 超时自动触发
    - 减少系统调用次数
    
    Example:
        processor = BatchProcessor(
            batch_handler=lambda items: db.bulk_insert(items),
            batch_size=100,
            timeout=1.0
        )
        for item in items:
            processor.add(item)
        processor.flush()
    """
    __slots__ = ('_handler', '_batch_size', '_timeout', '_buffer', '_last_flush', '_processed_count')
    
    def __init__(self, batch_handler: Callable[[List[T]], Any], batch_size: int = 100, timeout: float = 1.0):
        self._handler = batch_handler
        self._batch_size = batch_size
        self._timeout = timeout
        self._buffer: List[T] = []
        self._last_flush = time.time()
        self._processed_count = 0
    
    def add(self, item: T):
        """添加项目到缓冲区"""
        self._buffer.append(item)
        
        # 检查是否需要批量处理
        if len(self._buffer) >= self._batch_size:
            self.flush()
        elif time.time() - self._last_flush > self._timeout:
            self.flush()
    
    def flush(self):
        """强制刷新缓冲区"""
        if not self._buffer:
            return
        
        self._handler(self._buffer)
        self._buffer.clear()
        self._last_flush = time.time()
        self._processed_count += 1
    
    @property
    def pending_count(self) -> int:
        return len(self._buffer)
    
    def stats(self) -> dict[str, Any]:
        return {
            "pending": len(self._buffer),
            "batch_size": self._batch_size,
            "flush_count": self._processed_count,
        }


# ========== 内存预分配器 ==========
class MemoryArena:
    """内存预分配器
    
    特性:
    - 预分配大块内存
    - 按需切分
    - 减少内存碎片
    
    Example:
        arena = MemoryArena(size=1024*1024)  # 1MB
        chunk = arena.allocate(256)
        # ... use chunk ...
        arena.deallocate(chunk)
    """
    __slots__ = ('_data', '_free_list', '_allocated', '_total_size')
    
    def __init__(self, size: int = 1024 * 1024):
        self._data = bytearray(size)
        self._free_list: List[tuple[int, int]] = [(0, size)]  # (offset, size)
        self._allocated: Set[int] = set()
        self._total_size = size
    
    def allocate(self, size: int) -> Optional[memoryview]:
        """分配内存块"""
        # 首次适配算法
        for i, (offset, block_size) in enumerate(self._free_list):
            if block_size >= size:
                # 从空闲列表移除
                self._free_list.pop(i)
                
                # 如果有剩余，添加回空闲列表
                if block_size > size:
                    self._free_list.append((offset + size, block_size - size))
                
                self._allocated.add(offset)
                return memoryview(self._data)[offset:offset + size]
        
        return None
    
    def deallocate(self, view: memoryview):
        """释放内存块"""
        offset = view.obj.__array_interface__['data'][0] - id(self._data) if hasattr(view.obj, '__array_interface__') else 0
        # 简化：实际实现需要更复杂的合并逻辑
        if offset in self._allocated:
            self._allocated.remove(offset)
            self._free_list.append((offset, len(view)))
    
    @property
    def available(self) -> int:
        return sum(size for _, size in self._free_list)
    
    @property
    def usage_rate(self) -> float:
        return 1.0 - (self.available / self._total_size)


# ========== 热点路径优化器 ==========
class HotPathOptimizer:
    """热点代码路径优化器
    
    特性:
    - 自动检测热点函数
    - 动态应用优化
    - 性能监控
    """
    __slots__ = ('_call_counts', '_threshold', '_optimized', '_start_times')
    
    def __init__(self, threshold: int = 1000):
        self._call_counts: Dict[str, int] = {}
        self._threshold = threshold
        self._optimized: Set[str] = set()
        self._start_times: Dict[str, float] = {}
    
    def track(self, func_name: str):
        """跟踪函数调用"""
        now = time.time()
        
        if func_name not in self._call_counts:
            self._call_counts[func_name] = 0
            self._start_times[func_name] = now
        
        self._call_counts[func_name] += 1
        
        # 检测是否为热点
        if self._call_counts[func_name] >= self._threshold and func_name not in self._optimized:
            self._optimized.add(func_name)
            elapsed = now - self._start_times[func_name]
            return True, elapsed
        
        return False, 0.0
    
    def is_hot(self, func_name: str) -> bool:
        return func_name in self._optimized
    
    def stats(self) -> dict[str, Any]:
        return {
            "tracked_functions": len(self._call_counts),
            "hot_functions": list(self._optimized),
            "threshold": self._threshold,
        }


# ========== 性能分析器 ==========
class PerfProfiler:
    """轻量级性能分析器
    
    特性:
    - 低开销计时
    - 嵌套支持
    - 统计汇总
    """
    __slots__ = ('_records', '_stack', '_enabled')
    
    def __init__(self):
        self._records: Dict[str, List[float]] = {}
        self._stack: List[tuple[str, float]] = []
        self._enabled = True
    
    def start(self, name: str):
        if not self._enabled:
            return
        self._stack.append((name, time.perf_counter()))
    
    def stop(self, name: str):
        if not self._enabled or not self._stack:
            return
        
        top_name, start_time = self._stack.pop()
        if top_name != name:
            return
        
        elapsed = time.perf_counter() - start_time
        if name not in self._records:
            self._records[name] = []
        self._records[name].append(elapsed)
    
    def context(self, name: str):
        """上下文管理器"""
        return _PerfContext(self, name)
    
    def stats(self) -> dict[str, Any]:
        result = {}
        for name, times in self._records.items():
            if times:
                result[name] = {
                    "count": len(times),
                    "total": sum(times),
                    "avg": sum(times) / len(times),
                    "min": min(times),
                    "max": max(times),
                }
        return result
    
    def clear(self):
        self._records.clear()
        self._stack.clear()
    
    def disable(self):
        self._enabled = False
    
    def enable(self):
        self._enabled = True


class _PerfContext:
    def __init__(self, profiler: PerfProfiler, name: str):
        self._profiler = profiler
        self._name = name
    
    def __enter__(self):
        self._profiler.start(self._name)
        return self
    
    def __exit__(self, *args):
        self._profiler.stop(self._name)


# ========== 字符串优化 ==========
class StringIntern:
    """字符串驻留优化器
    
    特性:
    - 重复字符串去重
    - 减少内存占用
    - 加速字符串比较
    
    注意：Python 内置的 sys.intern() 已经对字符串做了弱引用处理，
    这里使用强引用缓存来确保常用字符串不会被回收。
    """
    __slots__ = ('_cache',)
    
    def __init__(self, use_weak_refs: bool = True):
        # 字符串本身不支持弱引用，所以只使用普通 dict
        self._cache: Dict[str, str] = {}
    
    def intern(self, s: str) -> str:
        if s in self._cache:
            return self._cache[s]
        
        # 使用 Python 内置的字符串驻留
        import sys
        interned = sys.intern(s)
        self._cache[interned] = interned
        
        return interned
    
    def clear(self):
        self._cache.clear()


# ========== 主插件类 ==========
class PerformanceOptimizerPlugin:
    """性能优化插件"""
    
    def __init__(self):
        self._initialized = False
        self._caches: Dict[str, FastCache] = {}
        self._pools: Dict[str, ObjectPool] = {}
        self._profiler = PerfProfiler()
        self._string_intern = StringIntern()
        self._hot_path = HotPathOptimizer()
    
    def init(self, deps: Optional[dict[str, Any]] = None):
        """初始化插件"""
        if self._initialized:
            return
        
        # 注册全局缓存
        self._caches["route_match"] = FastCache(maxsize=2048)
        self._caches["path_params"] = FastCache(maxsize=2048)
        self._caches["template_render"] = FastCache(maxsize=512)
        
        # 注册对象池
        self._pools["bytearray_4k"] = ObjectPool(lambda: bytearray(4096), maxsize=100)
        self._pools["bytearray_64k"] = ObjectPool(lambda: bytearray(65536), maxsize=20)
        
        self._initialized = True
    
    def start(self):
        """启动插件"""
        pass
    
    def stop(self):
        """停止插件"""
        for cache in self._caches.values():
            cache.clear()
        for pool in self._pools.values():
            pool.clear()
        self._profiler.clear()
    
    def get_cache(self, name: str) -> Optional[FastCache]:
        return self._caches.get(name)
    
    def get_pool(self, name: str) -> Optional[ObjectPool]:
        return self._pools.get(name)
    
    def profile(self) -> PerfProfiler:
        return self._profiler
    
    def intern_string(self, s: str) -> str:
        return self._string_intern.intern(s)
    
    def track_hot_path(self, func_name: str) -> tuple[bool, float]:
        return self._hot_path.track(func_name)
    
    def stats(self) -> dict[str, Any]:
        return {
            "caches": {name: cache.stats() for name, cache in self._caches.items()},
            "pools": {name: pool.stats() for name, pool in self._pools.items()},
            "profiler": self._profiler.stats(),
            "hot_paths": self._hot_path.stats(),
        }


def New() -> PerformanceOptimizerPlugin:
    """工厂函数"""
    return PerformanceOptimizerPlugin()
