"""
队列管理器模块
管理等待匹配的玩家队列
"""

import time
import threading
import uuid
from typing import Dict, Any, List, Optional
from collections import deque

class QueueManager:
    """
    队列管理器
    管理等待匹配的玩家队列
    """
    
    def __init__(self, plugin):
        """
        初始化队列管理器
        
        Args:
            plugin: 匹配系统插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 队列配置
        self.queue_config = {
            "default_queue_timeout": 300.0,  # 5分钟
            "queue_processing_interval": 2.0,
            "max_players_per_match": 100,
            "min_players_per_match": 2,
            "enable_queue_prioritization": True,
            "enable_skill_based_queue": True,
            "enable_region_based_queue": True
        }
        
        # 队列状态
        self.queue_state = {
            "total_players": 0,
            "active_queues": 0,
            "players_matched": 0,
            "players_timed_out": 0
        }
        
        # 队列存储
        self.queues = {}  # 按游戏模式分类的队列
        self.player_queues = {}  # 玩家所在的队列映射
        self.queue_lock = threading.RLock()
        
        # 队列统计
        self.queue_stats = {
            "players_added": 0,
            "players_removed": 0,
            "matches_created": 0,
            "queue_timeouts": 0,
            "queue_errors": 0
        }
        
        # 回调函数
        self.queue_callbacks = {
            "player_queued": [],
            "player_dequeued": [],
            "match_found": [],
            "queue_timeout": [],
            "queue_error": []
        }
        
        # 时间戳记录
        self.last_queue_process = 0.0
        self.last_cleanup = 0.0
        
        print("✓ 队列管理器已创建")
        
    def initialize(self) -> bool:
        """
        初始化队列管理器
        
        Returns:
            是否初始化成功
        """
        try:
            print("正在初始化队列管理器...")
            
            self.initialized = True
            print("✓ 队列管理器初始化完成")
            return True
            
        except Exception as e:
            print(f"✗ 队列管理器初始化失败: {e}")
            self.queue_stats["queue_errors"] += 1
            import traceback
            traceback.print_exc()
            return False
            
    def enable(self) -> bool:
        """
        启用队列管理器
        
        Returns:
            是否启用成功
        """
        try:
            if not self.initialized:
                print("✗ 队列管理器未初始化")
                return False
                
            self.enabled = True
            print("✓ 队列管理器已启用")
            return True
            
        except Exception as e:
            print(f"✗ 队列管理器启用失败: {e}")
            self.queue_stats["queue_errors"] += 1
            import traceback
            traceback.print_exc()
            return False
            
    def disable(self):
        """禁用队列管理器"""
        try:
            self.enabled = False
            
            # 清空所有队列
            with self.queue_lock:
                self.queues.clear()
                self.player_queues.clear()
                
            print("✓ 队列管理器已禁用")
            
        except Exception as e:
            print(f"✗ 队列管理器禁用失败: {e}")
            self.queue_stats["queue_errors"] += 1
            import traceback
            traceback.print_exc()
            
    def finalize(self):
        """清理队列管理器资源"""
        try:
            # 禁用队列管理器
            if self.enabled:
                self.disable()
                
            # 清理回调
            self.queue_callbacks.clear()
            
            self.initialized = False
            print("✓ 队列管理器资源已清理")
            
        except Exception as e:
            print(f"✗ 队列管理器资源清理失败: {e}")
            import traceback
            traceback.print_exc()
            
    def update(self, dt: float):
        """
        更新队列管理器状态
        
        Args:
            dt: 时间增量（秒）
        """
        try:
            if not self.enabled:
                return
                
            current_time = time.time()
            
            # 定期处理队列
            if current_time - self.last_queue_process >= self.queue_config["queue_processing_interval"]:
                self.process_queues()
                self.last_queue_process = current_time
                
            # 定期清理
            if current_time - self.last_cleanup >= 60.0:  # 每分钟清理一次
                self._cleanup_expired_players(current_time)
                self.last_cleanup = current_time
                
        except Exception as e:
            print(f"✗ 队列管理器更新失败: {e}")
            self.queue_stats["queue_errors"] += 1
            import traceback
            traceback.print_exc()
            
    def _cleanup_expired_players(self, current_time: float):
        """清理过期玩家"""
        try:
            expired_players = []
            with self.queue_lock:
                for player_id, queue_info in self.player_queues.items():
                    join_time = queue_info["join_time"]
                    timeout = queue_info.get("timeout", self.queue_config["default_queue_timeout"])
                    
                    if current_time - join_time > timeout:
                        expired_players.append(player_id)
                        
            # 移除过期玩家
            for player_id in expired_players:
                self._remove_player_from_queue(player_id, "timeout")
                self.queue_stats["queue_timeouts"] += 1
                
                # 触发队列超时回调
                self._trigger_queue_callback("queue_timeout", {
                    "player_id": player_id,
                    "timestamp": current_time
                })
                
        except Exception as e:
            print(f"✗ 过期玩家清理失败: {e}")
            self.queue_stats["queue_errors"] += 1
            
    def add_players_to_queue(self, player_ids: List[str], queue_params: Dict[str, Any]) -> bool:
        """
        添加玩家到队列
        
        Args:
            player_ids: 玩家ID列表
            queue_params: 队列参数
            
        Returns:
            是否添加成功
        """
        try:
            if not self.enabled:
                return False
                
            queue_name = queue_params.get("queue_name", "default")
            game_mode = queue_params.get("game_mode", "default")
            region = queue_params.get("region", "global")
            skill_level = queue_params.get("skill_level", 0)
            timeout = queue_params.get("timeout", self.queue_config["default_queue_timeout"])
            
            with self.queue_lock:
                # 创建队列（如果不存在）
                if queue_name not in self.queues:
                    self.queues[queue_name] = {
                        "name": queue_name,
                        "game_mode": game_mode,
                        "region": region,
                        "players": deque(),
                        "created_time": time.time()
                    }
                    self.queue_state["active_queues"] += 1
                    
                # 添加玩家到队列
                queue = self.queues[queue_name]
                for player_id in player_ids:
                    player_info = {
                        "player_id": player_id,
                        "skill_level": skill_level,
                        "region": region,
                        "join_time": time.time(),
                        "timeout": timeout,
                        "queue_params": queue_params
                    }
                    
                    queue["players"].append(player_info)
                    self.player_queues[player_id] = {
                        "queue_name": queue_name,
                        "join_time": time.time(),
                        "timeout": timeout
                    }
                    
                self.queue_state["total_players"] += len(player_ids)
                self.queue_stats["players_added"] += len(player_ids)
                
            # 触发玩家入队回调
            self._trigger_queue_callback("player_queued", {
                "player_ids": player_ids,
                "queue_name": queue_name,
                "game_mode": game_mode,
                "timestamp": time.time()
            })
            
            print(f"✓ {len(player_ids)}名玩家已添加到队列: {queue_name}")
            return True
            
        except Exception as e:
            print(f"✗ 玩家添加到队列失败: {e}")
            self.queue_stats["queue_errors"] += 1
            return False
            
    def remove_players_from_queue(self, match_id: str = None, player_ids: List[str] = None) -> bool:
        """
        从队列移除玩家
        
        Args:
            match_id: 匹配ID（可选）
            player_ids: 玩家ID列表（可选）
            
        Returns:
            是否移除成功
        """
        try:
            if not self.enabled:
                return False
                
            removed_count = 0
            
            if player_ids:
                # 移除指定玩家
                for player_id in player_ids:
                    if self._remove_player_from_queue(player_id):
                        removed_count += 1
            else:
                # 移除所有玩家（这种情况较少使用）
                with self.queue_lock:
                    player_ids = list(self.player_queues.keys())
                    for player_id in player_ids:
                        if self._remove_player_from_queue(player_id):
                            removed_count += 1
                            
            self.queue_stats["players_removed"] += removed_count
            
            # 触发玩家离队回调
            if player_ids:
                self._trigger_queue_callback("player_dequeued", {
                    "player_ids": player_ids,
                    "match_id": match_id,
                    "timestamp": time.time()
                })
                
            print(f"✓ {removed_count}名玩家已从队列移除")
            return removed_count > 0
            
        except Exception as e:
            print(f"✗ 玩家从队列移除失败: {e}")
            self.queue_stats["queue_errors"] += 1
            return False
            
    def _remove_player_from_queue(self, player_id: str, reason: str = "manual") -> bool:
        """
        从队列移除单个玩家
        
        Args:
            player_id: 玩家ID
            reason: 移除原因
            
        Returns:
            是否移除成功
        """
        try:
            with self.queue_lock:
                if player_id not in self.player_queues:
                    return False
                    
                queue_name = self.player_queues[player_id]["queue_name"]
                del self.player_queues[player_id]
                
                # 从队列中移除玩家
                if queue_name in self.queues:
                    queue = self.queues[queue_name]
                    players = queue["players"]
                    
                    # 查找并移除玩家
                    player_found = False
                    for i, player_info in enumerate(list(players)):
                        if player_info["player_id"] == player_id:
                            del players[i]
                            player_found = True
                            break
                            
                    # 如果队列为空，移除队列
                    if len(players) == 0:
                        del self.queues[queue_name]
                        self.queue_state["active_queues"] -= 1
                        
                    if player_found:
                        self.queue_state["total_players"] -= 1
                        return True
                        
            return False
            
        except Exception as e:
            print(f"✗ 玩家从队列移除失败: {e}")
            self.queue_stats["queue_errors"] += 1
            return False
            
    def process_queues(self):
        """处理队列（寻找匹配）"""
        try:
            if not self.enabled:
                return
                
            with self.queue_lock:
                queue_names = list(self.queues.keys())
                
            for queue_name in queue_names:
                self._process_queue(queue_name)
                
        except Exception as e:
            print(f"✗ 队列处理失败: {e}")
            self.queue_stats["queue_errors"] += 1
            
    def _process_queue(self, queue_name: str):
        """
        处理单个队列
        
        Args:
            queue_name: 队列名称
        """
        try:
            with self.queue_lock:
                if queue_name not in self.queues:
                    return
                    
                queue = self.queues[queue_name]
                players = list(queue["players"])
                
            # 检查是否有足够的玩家进行匹配
            min_players = self.queue_config["min_players_per_match"]
            max_players = self.queue_config["max_players_per_match"]
            
            if len(players) >= min_players:
                # 确定匹配的玩家数量
                match_player_count = min(len(players), max_players)
                
                # 选择玩家（简化实现，实际中可能需要考虑技能匹配等因素）
                selected_players = players[:match_player_count]
                
                # 创建匹配
                if self._create_match(selected_players, queue):
                    # 从队列中移除已匹配的玩家
                    for player_info in selected_players:
                        self._remove_player_from_queue(player_info["player_id"])
                        
                    self.queue_state["players_matched"] += len(selected_players)
                    self.queue_stats["matches_created"] += 1
                    
        except Exception as e:
            print(f"✗ 队列处理失败: {e}")
            self.queue_stats["queue_errors"] += 1
            
    def _create_match(self, players: List[Dict[str, Any]], queue: Dict[str, Any]) -> bool:
        """
        创建匹配
        
        Args:
            players: 玩家列表
            queue: 队列信息
            
        Returns:
            是否创建成功
        """
        try:
            # 生成匹配ID
            match_id = f"match_{int(time.time() * 1000000)}"
            
            # 提取玩家ID
            player_ids = [player["player_id"] for player in players]
            
            # 创建房间
            room_id = None
            if self.plugin.room_allocator:
                room_settings = {
                    "game_mode": queue["game_mode"],
                    "region": queue["region"],
                    "max_players": len(players)
                }
                
                room_id = self.plugin.room_allocator.create_room(
                    room_name=f"Match_{match_id[:8]}", 
                    room_settings=room_settings
                )
                
            # 添加玩家到房间
            if room_id and self.plugin.room_allocator:
                for player_id in player_ids:
                    self.plugin.room_allocator.add_client_to_room(room_id, player_id)
                    
            # 通知匹配管理器匹配完成
            if self.plugin.match_manager:
                self.plugin.match_manager.complete_match(match_id, room_id or "")
                
            # 触发匹配找到回调
            self._trigger_queue_callback("match_found", {
                "match_id": match_id,
                "room_id": room_id,
                "player_ids": player_ids,
                "queue_name": queue["name"],
                "timestamp": time.time()
            })
            
            print(f"✓ 匹配已创建: {match_id} ({len(player_ids)}名玩家)")
            return True
            
        except Exception as e:
            print(f"✗ 匹配创建失败: {e}")
            self.queue_stats["queue_errors"] += 1
            return False
            
    def get_queue_info(self, queue_name: str = None) -> Dict[str, Any]:
        """
        获取队列信息
        
        Args:
            queue_name: 队列名称（可选，如果未指定则返回所有队列信息）
            
        Returns:
            队列信息字典
        """
        try:
            with self.queue_lock:
                if queue_name:
                    if queue_name in self.queues:
                        queue = self.queues[queue_name]
                        return {
                            "name": queue["name"],
                            "game_mode": queue["game_mode"],
                            "region": queue["region"],
                            "player_count": len(queue["players"]),
                            "created_time": queue["created_time"]
                        }
                    else:
                        return {}
                else:
                    # 返回所有队列信息
                    queue_info = {}
                    for name, queue in self.queues.items():
                        queue_info[name] = {
                            "name": queue["name"],
                            "game_mode": queue["game_mode"],
                            "region": queue["region"],
                            "player_count": len(queue["players"]),
                            "created_time": queue["created_time"]
                        }
                    return queue_info
                    
        except Exception as e:
            print(f"✗ 队列信息获取失败: {e}")
            self.queue_stats["queue_errors"] += 1
            return {}
            
    def get_player_queue_info(self, player_id: str) -> Optional[Dict[str, Any]]:
        """
        获取玩家队列信息
        
        Args:
            player_id: 玩家ID
            
        Returns:
            玩家队列信息或None
        """
        try:
            with self.queue_lock:
                if player_id in self.player_queues:
                    return self.player_queues[player_id].copy()
                else:
                    return None
                    
        except Exception as e:
            print(f"✗ 玩家队列信息获取失败: {e}")
            self.queue_stats["queue_errors"] += 1
            return None
            
    def get_queue_stats(self) -> Dict[str, Any]:
        """
        获取队列统计信息
        
        Returns:
            队列统计字典
        """
        return {
            "state": self.queue_state.copy(),
            "stats": self.queue_stats.copy(),
            "config": self.queue_config.copy(),
            "current_queues": len(self.queues),
            "current_players": len(self.player_queues)
        }
        
    def reset_stats(self):
        """重置队列统计信息"""
        try:
            self.queue_stats = {
                "players_added": 0,
                "players_removed": 0,
                "matches_created": 0,
                "queue_timeouts": 0,
                "queue_errors": 0
            }
            print("✓ 队列统计信息已重置")
        except Exception as e:
            print(f"✗ 队列统计信息重置失败: {e}")
            
    def set_queue_config(self, config: Dict[str, Any]) -> bool:
        """
        设置队列配置
        
        Args:
            config: 队列配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.queue_config.update(config)
            print(f"✓ 队列配置已更新: {self.queue_config}")
            return True
        except Exception as e:
            print(f"✗ 队列配置设置失败: {e}")
            return False
            
    def get_queue_config(self) -> Dict[str, Any]:
        """
        获取队列配置
        
        Returns:
            队列配置字典
        """
        return self.queue_config.copy()
        
    def _trigger_queue_callback(self, callback_type: str, data: Dict[str, Any]):
        """
        触发队列回调
        
        Args:
            callback_type: 回调类型
            data: 回调数据
        """
        try:
            if callback_type in self.queue_callbacks:
                for callback in self.queue_callbacks[callback_type]:
                    try:
                        callback(data)
                    except Exception as e:
                        print(f"✗ 队列回调执行失败: {callback_type} - {e}")
        except Exception as e:
            print(f"✗ 队列回调触发失败: {e}")
            
    def register_queue_callback(self, callback_type: str, callback: callable):
        """
        注册队列回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.queue_callbacks:
                self.queue_callbacks[callback_type].append(callback)
                print(f"✓ 队列回调已注册: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 队列回调注册失败: {e}")
            
    def unregister_queue_callback(self, callback_type: str, callback: callable):
        """
        注销队列回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.queue_callbacks:
                if callback in self.queue_callbacks[callback_type]:
                    self.queue_callbacks[callback_type].remove(callback)
                    print(f"✓ 队列回调已注销: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 队列回调注销失败: {e}")