"""
网络管理器模块
负责处理网络连接和数据传输
"""

import time
import socket
import threading
from typing import Dict, Any, List, Optional
import json
import struct

class NetworkManager:
    """
    网络管理器
    负责处理网络连接和数据传输
    """
    
    def __init__(self, plugin):
        """
        初始化网络管理器
        
        Args:
            plugin: 网络同步插件实例
        """
        self.plugin = plugin
        self.enabled = False
        self.initialized = False
        
        # 网络配置
        self.network_config = {
            'server_host': 'localhost',
            'server_port': 7777,
            'max_connections': 32,
            'buffer_size': 4096,
            'timeout': 30.0,
            'heartbeat_interval': 5.0,
            'enable_compression': True,
            'enable_encryption': False,
            'protocol_version': '1.0'
        }
        
        # 服务器相关
        self.server_socket = None
        self.server_thread = None
        self.is_server_running = False
        self.server_clients = {}  # 客户端连接
        
        # 客户端相关
        self.client_socket = None
        self.client_thread = None
        self.is_client_connected = False
        self.client_id = None
        
        # 连接状态
        self.connection_state = {
            'is_connected': False,
            'connection_time': 0.0,
            'last_heartbeat': 0.0,
            'bytes_sent': 0,
            'bytes_received': 0,
            'packets_sent': 0,
            'packets_received': 0
        }
        
        # 网络统计
        self.network_stats = {
            'connections_accepted': 0,
            'connections_rejected': 0,
            'connections_lost': 0,
            'data_sent': 0,
            'data_received': 0,
            'packets_sent': 0,
            'packets_received': 0,
            'network_errors': 0
        }
        
        # 消息队列
        self.message_queue = []
        self.message_lock = threading.Lock()
        
        # 回调函数
        self.network_callbacks = {
            'client_connected': [],
            'client_disconnected': [],
            'data_received': [],
            'network_error': [],
            'server_started': [],
            'server_stopped': []
        }
        
        # 时间戳记录
        self.last_heartbeat_time = 0.0
        self.last_network_update = 0.0
        
        print("✓ 网络管理器已创建")
        
    def initialize(self) -> bool:
        """
        初始化网络管理器
        
        Returns:
            是否初始化成功
        """
        try:
            self.initialized = True
            print("✓ 网络管理器初始化完成")
            return True
            
        except Exception as e:
            print(f"✗ 网络管理器初始化失败: {e}")
            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}")
            import traceback
            traceback.print_exc()
            return False
            
    def disable(self):
        """禁用网络管理器"""
        try:
            self.enabled = False
            
            # 停止服务器
            if self.is_server_running:
                self.stop_server()
                
            # 断开客户端
            if self.is_client_connected:
                self.disconnect_client()
                
            print("✓ 网络管理器已禁用")
            
        except Exception as e:
            print(f"✗ 网络管理器禁用失败: {e}")
            import traceback
            traceback.print_exc()
            
    def finalize(self):
        """清理网络管理器资源"""
        try:
            self.disable()
            self.network_callbacks.clear()
            self.server_clients.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()
            self.last_network_update = current_time
            
            # 处理消息队列
            self._process_message_queue()
            
            # 发送心跳包
            if current_time - self.last_heartbeat_time >= self.network_config['heartbeat_interval']:
                self._send_heartbeat()
                self.last_heartbeat_time = current_time
                
        except Exception as e:
            print(f"✗ 网络管理器更新失败: {e}")
            import traceback
            traceback.print_exc()
            
    def _process_message_queue(self):
        """处理消息队列"""
        try:
            with self.message_lock:
                while self.message_queue:
                    message = self.message_queue.pop(0)
                    self._handle_message(message)
        except Exception as e:
            print(f"✗ 消息队列处理失败: {e}")
            
    def _handle_message(self, message: Dict[str, Any]):
        """
        处理消息
        
        Args:
            message: 消息数据
        """
        try:
            message_type = message.get('type')
            message_data = message.get('data')
            client_id = message.get('client_id')
            
            # 触发数据接收回调
            self._trigger_network_callback('data_received', {
                'type': message_type,
                'data': message_data,
                'client_id': client_id
            })
            
            # 根据消息类型处理
            if message_type == 'sync_data':
                self._handle_sync_data(message_data, client_id)
            elif message_type == 'heartbeat':
                self._handle_heartbeat(message_data, client_id)
            elif message_type == 'connect':
                self._handle_connect(message_data, client_id)
            elif message_type == 'disconnect':
                self._handle_disconnect(message_data, client_id)
                
        except Exception as e:
            print(f"✗ 消息处理失败: {e}")
            self.network_stats['network_errors'] += 1
            
    def _handle_sync_data(self, data: Dict[str, Any], client_id: str):
        """
        处理同步数据
        
        Args:
            data: 同步数据
            client_id: 客户端ID
        """
        try:
            # 将同步数据传递给对象同步模块
            if self.plugin.object_sync:
                for obj_id, obj_data in data.items():
                    self.plugin.object_sync.receive_sync_data(obj_id, obj_data, client_id)
        except Exception as e:
            print(f"✗ 同步数据处理失败: {e}")
            
    def _handle_heartbeat(self, data: Dict[str, Any], client_id: str):
        """
        处理心跳包
        
        Args:
            data: 心跳数据
            client_id: 客户端ID
        """
        try:
            # 更新客户端最后心跳时间
            if client_id in self.server_clients:
                self.server_clients[client_id]['last_heartbeat'] = time.time()
        except Exception as e:
            print(f"✗ 心跳包处理失败: {e}")
            
    def _handle_connect(self, data: Dict[str, Any], client_id: str):
        """
        处理连接消息
        
        Args:
            data: 连接数据
            client_id: 客户端ID
        """
        try:
            # 触发客户端连接回调
            self._trigger_network_callback('client_connected', {
                'client_id': client_id,
                'data': data
            })
        except Exception as e:
            print(f"✗ 连接消息处理失败: {e}")
            
    def _handle_disconnect(self, data: Dict[str, Any], client_id: str):
        """
        处理断开连接消息
        
        Args:
            data: 断开连接数据
            client_id: 客户端ID
        """
        try:
            # 从客户端列表中移除
            if client_id in self.server_clients:
                del self.server_clients[client_id]
                
            # 触发客户端断开连接回调
            self._trigger_network_callback('client_disconnected', {
                'client_id': client_id,
                'data': data
            })
        except Exception as e:
            print(f"✗ 断开连接消息处理失败: {e}")
            
    def start_server(self, port: int = None) -> bool:
        """
        启动服务器
        
        Args:
            port: 服务器端口
            
        Returns:
            是否启动成功
        """
        try:
            if self.is_server_running:
                print("✗ 服务器已在运行")
                return False
                
            if port is None:
                port = self.network_config['server_port']
                
            # 创建服务器套接字
            self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
            self.server_socket.bind((self.network_config['server_host'], port))
            self.server_socket.listen(self.network_config['max_connections'])
            self.server_socket.settimeout(1.0)  # 设置超时以便可以检查运行状态
            
            self.is_server_running = True
            self.network_config['server_port'] = port
            
            # 启动服务器线程
            self.server_thread = threading.Thread(target=self._server_loop, daemon=True)
            self.server_thread.start()
            
            # 触发服务器启动回调
            self._trigger_network_callback('server_started', {
                'host': self.network_config['server_host'],
                'port': port
            })
            
            print(f"✓ 服务器已启动: {self.network_config['server_host']}:{port}")
            return True
            
        except Exception as e:
            print(f"✗ 服务器启动失败: {e}")
            import traceback
            traceback.print_exc()
            return False
            
    def stop_server(self):
        """停止服务器"""
        try:
            self.is_server_running = False
            
            # 关闭所有客户端连接
            for client_id, client_data in list(self.server_clients.items()):
                try:
                    client_data['socket'].close()
                except Exception as e:
                    pass
                    
            self.server_clients.clear()
            
            # 关闭服务器套接字
            if self.server_socket:
                self.server_socket.close()
                self.server_socket = None
                
            # 等待服务器线程结束
            if self.server_thread and self.server_thread.is_alive():
                self.server_thread.join(timeout=2.0)
                
            # 触发服务器停止回调
            self._trigger_network_callback('server_stopped', {})
            
            print("✓ 服务器已停止")
            
        except Exception as e:
            print(f"✗ 服务器停止失败: {e}")
            
    def _server_loop(self):
        """服务器主循环"""
        try:
            print("✓ 服务器主循环已启动")
            
            while self.is_server_running:
                try:
                    # 接受客户端连接
                    client_socket, client_address = self.server_socket.accept()
                    
                    # 创建客户端线程
                    client_thread = threading.Thread(
                        target=self._handle_client, 
                        args=(client_socket, client_address),
                        daemon=True
                    )
                    client_thread.start()
                    
                    # 分配客户端ID
                    client_id = f"client_{int(time.time() * 1000)}"
                    
                    # 添加到客户端列表
                    self.server_clients[client_id] = {
                        'socket': client_socket,
                        'address': client_address,
                        'thread': client_thread,
                        'connect_time': time.time(),
                        'last_heartbeat': time.time(),
                        'bytes_sent': 0,
                        'bytes_received': 0
                    }
                    
                    self.network_stats['connections_accepted'] += 1
                    print(f"✓ 客户端已连接: {client_address} ({client_id})")
                    
                except socket.timeout:
                    # 正常超时，继续循环
                    continue
                except Exception as e:
                    if self.is_server_running:
                        print(f"✗ 接受客户端连接失败: {e}")
                        self.network_stats['network_errors'] += 1
                        
        except Exception as e:
            print(f"✗ 服务器主循环失败: {e}")
        finally:
            print("✓ 服务器主循环已结束")
            
    def _handle_client(self, client_socket: socket.socket, client_address: tuple):
        """
        处理客户端连接
        
        Args:
            client_socket: 客户端套接字
            client_address: 客户端地址
        """
        client_id = None
        try:
            # 为客户端分配ID
            client_id = f"client_{hash(client_address)}_{int(time.time() * 1000)}"
            
            print(f"✓ 开始处理客户端: {client_address} ({client_id})")
            
            # 发送连接确认消息
            connect_message = {
                'type': 'connect_ack',
                'data': {
                    'client_id': client_id,
                    'server_time': time.time(),
                    'protocol_version': self.network_config['protocol_version']
                }
            }
            self._send_message(client_socket, connect_message)
            
            # 主接收循环
            while self.is_server_running:
                try:
                    # 接收消息
                    message = self._receive_message(client_socket)
                    if message is None:
                        # 客户端断开连接
                        break
                        
                    # 添加客户端ID到消息
                    message['client_id'] = client_id
                    
                    # 添加到消息队列
                    with self.message_lock:
                        self.message_queue.append(message)
                        
                    # 更新统计信息
                    self.network_stats['packets_received'] += 1
                    self.network_stats['data_received'] += len(str(message).encode('utf-8'))
                    
                except socket.timeout:
                    # 检查心跳超时
                    if client_id in self.server_clients:
                        last_heartbeat = self.server_clients[client_id]['last_heartbeat']
                        if time.time() - last_heartbeat > self.network_config['timeout']:
                            print(f"✗ 客户端心跳超时: {client_address} ({client_id})")
                            break
                    continue
                except Exception as e:
                    print(f"✗ 接收客户端消息失败: {e}")
                    break
                    
        except Exception as e:
            print(f"✗ 处理客户端连接失败: {e}")
        finally:
            # 清理客户端连接
            if client_id and client_id in self.server_clients:
                del self.server_clients[client_id]
                
            try:
                client_socket.close()
            except Exception as e:
                pass
                
            self.network_stats['connections_lost'] += 1
            print(f"✓ 客户端连接已断开: {client_address} ({client_id})")
            
            # 触发客户端断开连接回调
            self._trigger_network_callback('client_disconnected', {
                'client_id': client_id,
                'address': client_address
            })
            
    def connect_to_server(self, host: str = None, port: int = None) -> bool:
        """
        连接到服务器
        
        Args:
            host: 服务器地址
            port: 服务器端口
            
        Returns:
            是否连接成功
        """
        try:
            if self.is_client_connected:
                print("✗ 客户端已连接到服务器")
                return False
                
            if host is None:
                host = self.network_config['server_host']
                
            if port is None:
                port = self.network_config['server_port']
                
            # 创建客户端套接字
            self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.client_socket.settimeout(self.network_config['timeout'])
            
            # 连接服务器
            self.client_socket.connect((host, port))
            
            # 启动客户端接收线程
            self.client_thread = threading.Thread(target=self._client_receive_loop, daemon=True)
            self.client_thread.start()
            
            # 等待连接确认
            connect_ack = self._receive_message(self.client_socket)
            if connect_ack and connect_ack.get('type') == 'connect_ack':
                self.client_id = connect_ack['data']['client_id']
                self.is_client_connected = True
                self.connection_state['is_connected'] = True
                self.connection_state['connection_time'] = time.time()
                
                print(f"✓ 已连接到服务器: {host}:{port} (Client ID: {self.client_id})")
                return True
            else:
                print("✗ 服务器连接确认失败")
                self.disconnect_client()
                return False
                
        except Exception as e:
            print(f"✗ 连接服务器失败: {e}")
            import traceback
            traceback.print_exc()
            self.disconnect_client()
            return False
            
    def disconnect_client(self):
        """断开客户端连接"""
        try:
            self.is_client_connected = False
            self.connection_state['is_connected'] = False
            
            if self.client_socket:
                try:
                    # 发送断开连接消息
                    disconnect_message = {
                        'type': 'disconnect',
                        'data': {}
                    }
                    self._send_message(self.client_socket, disconnect_message)
                except Exception as e:
                    pass
                    
                self.client_socket.close()
                self.client_socket = None
                
            # 等待客户端线程结束
            if self.client_thread and self.client_thread.is_alive():
                self.client_thread.join(timeout=2.0)
                
            self.client_id = None
            print("✓ 客户端已断开连接")
            
        except Exception as e:
            print(f"✗ 客户端断开连接失败: {e}")
            
    def _client_receive_loop(self):
        """客户端接收循环"""
        try:
            while self.is_client_connected and self.client_socket:
                try:
                    # 接收消息
                    message = self._receive_message(self.client_socket)
                    if message is None:
                        # 服务器断开连接
                        break
                        
                    # 添加到消息队列
                    with self.message_lock:
                        self.message_queue.append(message)
                        
                    # 更新统计信息
                    self.network_stats['packets_received'] += 1
                    self.network_stats['data_received'] += len(str(message).encode('utf-8'))
                    
                except socket.timeout:
                    continue
                except Exception as e:
                    if self.is_client_connected:
                        print(f"✗ 接收服务器消息失败: {e}")
                    break
                    
        except Exception as e:
            print(f"✗ 客户端接收循环失败: {e}")
        finally:
            if self.is_client_connected:
                self.disconnect_client()
                
    def send_sync_data(self, data: Dict[str, Any], target_client_id: str = None) -> bool:
        """
        发送同步数据
        
        Args:
            data: 同步数据
            target_client_id: 目标客户端ID（None表示广播给所有客户端）
            
        Returns:
            是否发送成功
        """
        try:
            if not self.enabled:
                print("✗ 网络管理器未启用")
                return False
                
            message = {
                'type': 'sync_data',
                'data': data
            }
            
            # 服务器模式：广播给客户端
            if self.is_server_running:
                if target_client_id:
                    # 发送给特定客户端
                    if target_client_id in self.server_clients:
                        client_socket = self.server_clients[target_client_id]['socket']
                        return self._send_message(client_socket, message)
                    else:
                        print(f"✗ 目标客户端不存在: {target_client_id}")
                        return False
                else:
                    # 广播给所有客户端
                    success_count = 0
                    for client_id, client_data in self.server_clients.items():
                        try:
                            if self._send_message(client_data['socket'], message):
                                success_count += 1
                        except Exception as e:
                            print(f"✗ 向客户端 {client_id} 发送数据失败: {e}")
                            
                    return success_count > 0
                    
            # 客户端模式：发送给服务器
            elif self.is_client_connected:
                return self._send_message(self.client_socket, message)
            else:
                print("✗ 未连接到服务器")
                return False
                
        except Exception as e:
            print(f"✗ 同步数据发送失败: {e}")
            self.network_stats['network_errors'] += 1
            return False
            
    def _send_message(self, sock: socket.socket, message: Dict[str, Any]) -> bool:
        """
        发送消息
        
        Args:
            sock: 套接字
            message: 消息数据
            
        Returns:
            是否发送成功
        """
        try:
            # 序列化消息
            message_json = json.dumps(message, ensure_ascii=False)
            message_bytes = message_json.encode('utf-8')
            
            # 添加长度前缀
            message_length = len(message_bytes)
            length_prefix = struct.pack('!I', message_length)
            
            # 发送数据
            sock.sendall(length_prefix + message_bytes)
            
            # 更新统计信息
            self.network_stats['packets_sent'] += 1
            self.network_stats['data_sent'] += message_length
            
            if self.is_server_running:
                # 更新服务器统计
                pass
            elif self.is_client_connected:
                self.connection_state['bytes_sent'] += message_length
                self.connection_state['packets_sent'] += 1
                
            return True
            
        except Exception as e:
            print(f"✗ 消息发送失败: {e}")
            self.network_stats['network_errors'] += 1
            return False
            
    def _receive_message(self, sock: socket.socket) -> Optional[Dict[str, Any]]:
        """
        接收消息
        
        Args:
            sock: 套接字
            
        Returns:
            消息数据或None
        """
        try:
            # 接收长度前缀
            length_prefix = self._receive_all(sock, 4)
            if not length_prefix:
                return None
                
            message_length = struct.unpack('!I', length_prefix)[0]
            
            # 接收消息数据
            message_bytes = self._receive_all(sock, message_length)
            if not message_bytes:
                return None
                
            # 反序列化消息
            message_json = message_bytes.decode('utf-8')
            message = json.loads(message_json)
            
            # 更新统计信息
            self.network_stats['packets_received'] += 1
            self.network_stats['data_received'] += message_length
            
            if self.is_server_running:
                # 更新服务器统计
                pass
            elif self.is_client_connected:
                self.connection_state['bytes_received'] += message_length
                self.connection_state['packets_received'] += 1
                
            return message
            
        except Exception as e:
            print(f"✗ 消息接收失败: {e}")
            self.network_stats['network_errors'] += 1
            return None
            
    def _receive_all(self, sock: socket.socket, length: int) -> Optional[bytes]:
        """
        接收指定长度的数据
        
        Args:
            sock: 套接字
            length: 数据长度
            
        Returns:
            接收到的数据或None
        """
        try:
            data = b''
            while len(data) < length:
                packet = sock.recv(length - len(data))
                if not packet:
                    return None
                data += packet
            return data
        except Exception as e:
            print(f"✗ 数据接收失败: {e}")
            return None
            
    def _send_heartbeat(self):
        """发送心跳包"""
        try:
            heartbeat_message = {
                'type': 'heartbeat',
                'data': {
                    'timestamp': time.time()
                }
            }
            
            # 服务器模式：广播心跳包
            if self.is_server_running:
                for client_id, client_data in self.server_clients.items():
                    try:
                        self._send_message(client_data['socket'], heartbeat_message)
                    except Exception as e:
                        print(f"✗ 向客户端 {client_id} 发送心跳包失败: {e}")
                        
            # 客户端模式：发送心跳包到服务器
            elif self.is_client_connected:
                self._send_message(self.client_socket, heartbeat_message)
                
        except Exception as e:
            print(f"✗ 心跳包发送失败: {e}")
            
    def get_server_clients(self) -> Dict[str, Any]:
        """
        获取服务器客户端列表
        
        Returns:
            客户端列表
        """
        return self.server_clients.copy()
        
    def get_connection_state(self) -> Dict[str, Any]:
        """
        获取连接状态
        
        Returns:
            连接状态字典
        """
        return self.connection_state.copy()
        
    def set_network_config(self, config: Dict[str, Any]) -> bool:
        """
        设置网络配置
        
        Args:
            config: 配置字典
            
        Returns:
            是否设置成功
        """
        try:
            self.network_config.update(config)
            print(f"✓ 网络配置已更新: {self.network_config}")
            return True
        except Exception as e:
            print(f"✗ 网络配置设置失败: {e}")
            return False
            
    def get_network_config(self) -> Dict[str, Any]:
        """
        获取网络配置
        
        Returns:
            配置字典
        """
        return self.network_config.copy()
        
    def get_network_stats(self) -> Dict[str, Any]:
        """
        获取网络统计信息
        
        Returns:
            统计信息字典
        """
        return self.network_stats.copy()
        
    def reset_network_stats(self):
        """重置网络统计信息"""
        try:
            self.network_stats = {
                'connections_accepted': 0,
                'connections_rejected': 0,
                'connections_lost': 0,
                'data_sent': 0,
                'data_received': 0,
                'packets_sent': 0,
                'packets_received': 0,
                'network_errors': 0
            }
            print("✓ 网络统计信息已重置")
        except Exception as e:
            print(f"✗ 网络统计信息重置失败: {e}")
            
    def _trigger_network_callback(self, callback_type: str, data: Dict[str, Any]):
        """
        触发网络回调
        
        Args:
            callback_type: 回调类型
            data: 回调数据
        """
        try:
            if callback_type in self.network_callbacks:
                for callback in self.network_callbacks[callback_type]:
                    try:
                        callback(data)
                    except Exception as e:
                        print(f"✗ 网络回调执行失败: {e}")
        except Exception as e:
            print(f"✗ 网络回调触发失败: {e}")
            
    def register_network_callback(self, callback_type: str, callback: callable):
        """
        注册网络回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.network_callbacks:
                self.network_callbacks[callback_type].append(callback)
                print(f"✓ 网络回调已注册: {callback_type}")
            else:
                print(f"✗ 无效的回调类型: {callback_type}")
        except Exception as e:
            print(f"✗ 网络回调注册失败: {e}")
            
    def unregister_network_callback(self, callback_type: str, callback: callable):
        """
        注销网络回调
        
        Args:
            callback_type: 回调类型
            callback: 回调函数
        """
        try:
            if callback_type in self.network_callbacks:
                if callback in self.network_callbacks[callback_type]:
                    self.network_callbacks[callback_type].remove(callback)
                    print(f"✓ 网络回调已注销: {callback_type}")
        except Exception as e:
            print(f"✗ 网络回调注销失败: {e}")