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

"""
内存管理组件 - 新架构版本
专门负责智能内存管理，确保系统稳定运行
"""

import gc
import os
import time
import logging
import psutil
import threading
from typing import Dict, Any, Optional, Callable
from .text_renderer import PosterComponent

logger = logging.getLogger(__name__)


class MemoryManager(PosterComponent):
    """
    智能内存管理器
    监控内存使用，自动清理，防止内存溢出
    """
    
    def __init__(self):
        self.logger = logging.getLogger(__name__)
        self.memory_threshold = 0.8  # 80%内存阈值
        self.cleanup_callbacks = []  # 清理回调函数
        self.monitoring_enabled = False
        self.monitoring_thread = None
        self.monitoring_interval = 30  # 监控间隔（秒）
        
        # 内存统计
        self.stats = {
            'peak_usage': 0.0,
            'cleanup_count': 0,
            'last_cleanup': None
        }
    
    def initialize(self, config: Dict[str, Any]) -> None:
        """初始化内存管理器"""
        self.memory_threshold = config.get('memory_threshold', self.memory_threshold)
        self.monitoring_interval = config.get('monitoring_interval', self.monitoring_interval)
        
        # 启动监控
        auto_monitoring = config.get('auto_monitoring', True)
        if auto_monitoring:
            self.start_monitoring()
            
        self.logger.info(f"内存管理器初始化 - 阈值: {self.memory_threshold*100:.1f}%")
    
    def process(self, input_data: Any, **kwargs) -> Any:
        """处理内存管理请求"""
        if isinstance(input_data, dict):
            operation = input_data.get('operation')
            
            if operation == 'check_memory':
                return self.get_memory_info()
            elif operation == 'cleanup':
                return self.cleanup_memory()
            elif operation == 'register_callback':
                callback = input_data.get('callback')
                if callback:
                    self.register_cleanup_callback(callback)
                return True
                
        return None
    
    def cleanup(self) -> None:
        """清理内存管理器"""
        self.stop_monitoring()
        self.cleanup_memory()
    
    def get_memory_info(self) -> Dict[str, Any]:
        """
        获取详细内存信息
        
        Returns:
            内存信息字典
        """
        try:
            memory = psutil.virtual_memory()
            process = psutil.Process(os.getpid())
            process_memory = process.memory_info()
            
            info = {
                'system': {
                    'total_gb': memory.total / (1024**3),
                    'available_gb': memory.available / (1024**3),
                    'used_percent': memory.percent,
                    'free_gb': memory.free / (1024**3)
                },
                'process': {
                    'rss_mb': process_memory.rss / (1024**2),  # 物理内存
                    'vms_mb': process_memory.vms / (1024**2),  # 虚拟内存
                    'percent': process.memory_percent()
                },
                'pressure': {
                    'is_high': memory.percent > self.memory_threshold * 100,
                    'threshold': self.memory_threshold * 100,
                    'recommendation': self._get_memory_recommendation(memory.percent)
                },
                'stats': self.stats.copy()
            }
            
            # 更新峰值使用率
            if memory.percent > self.stats['peak_usage']:
                self.stats['peak_usage'] = memory.percent
            
            return info
            
        except Exception as e:
            self.logger.error(f"获取内存信息失败: {e}")
            return {'error': str(e)}
    
    def check_memory_pressure(self) -> bool:
        """
        检查内存压力
        
        Returns:
            True if memory pressure is high
        """
        try:
            memory = psutil.virtual_memory()
            used_percent = memory.percent
            available_mb = memory.available / (1024**2)
            
            # 多重检查条件
            high_usage = used_percent > self.memory_threshold * 100
            low_available = available_mb < 500  # 小于500MB可用
            
            if high_usage or low_available:
                self.logger.warning(
                    f"内存压力检测 - 使用率: {used_percent:.1f}%, "
                    f"可用: {available_mb:.1f}MB"
                )
                return True
                
            return False
            
        except Exception as e:
            self.logger.error(f"内存压力检查失败: {e}")
            return False
    
    def cleanup_memory(self) -> Dict[str, Any]:
        """
        执行内存清理
        
        Returns:
            清理结果
        """
        start_time = time.time()
        
        try:
            # 获取清理前的内存状态
            before_memory = psutil.virtual_memory().percent
            
            # 执行注册的清理回调
            callbacks_executed = 0
            for callback in self.cleanup_callbacks:
                try:
                    callback()
                    callbacks_executed += 1
                except Exception as e:
                    self.logger.error(f"清理回调执行失败: {e}")
            
            # 强制垃圾回收
            gc_collections = 0
            for generation in range(3):
                collected = gc.collect(generation)
                gc_collections += collected
            
            # 获取清理后的内存状态
            after_memory = psutil.virtual_memory().percent
            memory_freed = before_memory - after_memory
            
            # 更新统计
            self.stats['cleanup_count'] += 1
            self.stats['last_cleanup'] = time.time()
            
            cleanup_duration = time.time() - start_time
            
            result = {
                'success': True,
                'duration_seconds': cleanup_duration,
                'memory_before_percent': before_memory,
                'memory_after_percent': after_memory,
                'memory_freed_percent': memory_freed,
                'callbacks_executed': callbacks_executed,
                'gc_collections': gc_collections,
                'timestamp': time.time()
            }
            
            if memory_freed > 0:
                self.logger.info(
                    f"内存清理完成 - 释放: {memory_freed:.1f}%, "
                    f"耗时: {cleanup_duration:.2f}s"
                )
            
            return result
            
        except Exception as e:
            self.logger.error(f"内存清理失败: {e}")
            return {
                'success': False,
                'error': str(e),
                'timestamp': time.time()
            }
    
    def register_cleanup_callback(self, callback: Callable[[], None]) -> None:
        """
        注册清理回调函数
        
        Args:
            callback: 清理函数，无参数无返回值
        """
        if callback not in self.cleanup_callbacks:
            self.cleanup_callbacks.append(callback)
            self.logger.debug(f"注册清理回调，当前总数: {len(self.cleanup_callbacks)}")
    
    def unregister_cleanup_callback(self, callback: Callable[[], None]) -> None:
        """
        取消注册清理回调函数
        
        Args:
            callback: 要取消的清理函数
        """
        if callback in self.cleanup_callbacks:
            self.cleanup_callbacks.remove(callback)
            self.logger.debug(f"取消清理回调，当前总数: {len(self.cleanup_callbacks)}")
    
    def start_monitoring(self) -> None:
        """启动内存监控"""
        if self.monitoring_enabled:
            return
        
        self.monitoring_enabled = True
        self.monitoring_thread = threading.Thread(target=self._monitoring_loop, daemon=True)
        self.monitoring_thread.start()
        
        self.logger.info(f"内存监控已启动，间隔: {self.monitoring_interval}秒")
    
    def stop_monitoring(self) -> None:
        """停止内存监控"""
        self.monitoring_enabled = False
        
        if self.monitoring_thread and self.monitoring_thread.is_alive():
            self.monitoring_thread.join(timeout=5)
        
        self.logger.info("内存监控已停止")
    
    def _monitoring_loop(self) -> None:
        """监控循环"""
        while self.monitoring_enabled:
            try:
                if self.check_memory_pressure():
                    self.cleanup_memory()
                
                time.sleep(self.monitoring_interval)
                
            except Exception as e:
                self.logger.error(f"内存监控循环错误: {e}")
                time.sleep(self.monitoring_interval)
    
    def _get_memory_recommendation(self, usage_percent: float) -> str:
        """
        获取内存使用建议
        
        Args:
            usage_percent: 内存使用百分比
            
        Returns:
            建议文本
        """
        if usage_percent < 50:
            return "内存使用正常"
        elif usage_percent < 70:
            return "内存使用适中，可以继续运行"
        elif usage_percent < 85:
            return "内存使用较高，建议适时清理"
        elif usage_percent < 95:
            return "内存使用很高，强烈建议立即清理"
        else:
            return "内存使用临界，必须立即清理避免系统崩溃"
    
    def set_memory_threshold(self, threshold: float) -> None:
        """
        设置内存阈值
        
        Args:
            threshold: 新的阈值 (0.0-1.0)
        """
        if 0.1 <= threshold <= 0.95:
            old_threshold = self.memory_threshold
            self.memory_threshold = threshold
            self.logger.info(f"内存阈值已更新: {old_threshold*100:.1f}% -> {threshold*100:.1f}%")
        else:
            raise ValueError("内存阈值必须在10%-95%之间")
    
    def get_memory_stats(self) -> Dict[str, Any]:
        """获取内存统计信息"""
        return {
            'stats': self.stats.copy(),
            'current_info': self.get_memory_info(),
            'monitoring_enabled': self.monitoring_enabled,
            'cleanup_callbacks_count': len(self.cleanup_callbacks),
            'threshold_percent': self.memory_threshold * 100
        }
    
    def force_cleanup(self) -> Dict[str, Any]:
        """
        强制执行内存清理（无论是否达到阈值）
        
        Returns:
            清理结果
        """
        self.logger.info("执行强制内存清理")
        return self.cleanup_memory()
    
    def optimize_gc_settings(self) -> None:
        """优化垃圾回收设置"""
        try:
            # 获取当前GC阈值
            thresholds = gc.get_threshold()
            
            # 调整GC阈值以更频繁地清理（适合内存敏感应用）
            new_thresholds = (
                thresholds[0] // 2,  # 一代阈值减半
                thresholds[1] // 2,  # 二代阈值减半
                thresholds[2] // 2   # 三代阈值减半
            )
            
            gc.set_threshold(*new_thresholds)
            
            self.logger.info(f"GC阈值已优化: {thresholds} -> {new_thresholds}")
            
        except Exception as e:
            self.logger.error(f"优化GC设置失败: {e}")
    
    def reset_gc_settings(self) -> None:
        """重置垃圾回收设置到默认值"""
        try:
            gc.set_threshold(700, 10, 10)  # Python默认值
            self.logger.info("GC阈值已重置为默认值")
        except Exception as e:
            self.logger.error(f"重置GC设置失败: {e}") 