import math
import time
import random
import json
import socket
import threading
from dataclasses import dataclass, asdict
from typing import Tuple, Optional, Dict, Any
from datetime import datetime

@dataclass
class AimConfig:
    """瞄准配置类 - 支持JSON序列化"""
    aim_intensity: float = 99.9
    target: str = "敌人"
    target_part: str = "头部"
    head_lock: bool = True
    lock_strength: float = 99.9
    health_threshold: int = 1
    continuous_activation: bool = True
    damage_activation: bool = True
    console_output: bool = True
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典，用于JSON序列化"""
        return asdict(self)
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'AimConfig':
        """从字典创建配置实例"""
        return cls(**data)

class SmoothAimBot:
    """服务器端平滑锁头系统"""
    
    def __init__(self, config: AimConfig, server_port: int = 8080):
        self.config = config
        self.is_active = False
        self.current_target = None
        self.smooth_factor = 0.1
        self.last_aim_position = (0, 0, 0)
        self.server_port = server_port
        self.clients = []
        self.running = False
        
        # 初始化服务器日志
        self.log(f"平滑锁头系统初始化 - 端口: {server_port}")
        
        if config.console_output:
            self.log("Py：激活平滑锁头逻辑")
    
    def log(self, message: str):
        """服务器日志记录"""
        timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        print(f"[{timestamp}] SERVER: {message}")
    
    def start_server(self):
        """启动服务器监听"""
        self.running = True
        server_thread = threading.Thread(target=self._run_server, daemon=True)
        server_thread.start()
        self.log(f"服务器启动成功，监听端口 {self.server_port}")
    
    def stop_server(self):
        """停止服务器"""
        self.running = False
        self.log("服务器停止")
    
    def _run_server(self):
        """服务器主循环"""
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket:
                server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                server_socket.bind(('0.0.0.0', self.server_port))
                server_socket.listen(5)
                server_socket.settimeout(1.0)  # 设置超时以便检查运行状态
                
                while self.running:
                    try:
                        client_socket, address = server_socket.accept()
                        self.log(f"客户端连接: {address}")
                        client_thread = threading.Thread(
                            target=self._handle_client, 
                            args=(client_socket, address),
                            daemon=True
                        )
                        client_thread.start()
                        self.clients.append(client_socket)
                    except socket.timeout:
                        continue
                    except Exception as e:
                        self.log(f"服务器错误: {e}")
        except Exception as e:
            self.log(f"服务器启动失败: {e}")
    
    def _handle_client(self, client_socket: socket.socket, address: tuple):
        """处理客户端连接"""
        try:
            while self.running:
                # 接收客户端数据
                data = client_socket.recv(1024).decode('utf-8')
                if not data:
                    break
                
                # 解析JSON数据
                try:
                    message = json.loads(data)
                    response = self._process_message(message)
                    client_socket.send(json.dumps(response).encode('utf-8'))
                except json.JSONDecodeError:
                    self.log(f"无效的JSON数据: {data}")
                    client_socket.send(json.dumps({"status": "error", "message": "无效的JSON格式"}).encode('utf-8'))
                
        except Exception as e:
            self.log(f"客户端 {address} 处理错误: {e}")
        finally:
            client_socket.close()
            if client_socket in self.clients:
                self.clients.remove(client_socket)
            self.log(f"客户端断开: {address}")
    
    def _process_message(self, message: Dict[str, Any]) -> Dict[str, Any]:
        """处理客户端消息"""
        message_type = message.get('type', 'unknown')
        
        if message_type == 'aim_request':
            return self._handle_aim_request(message)
        elif message_type == 'config_update':
            return self._handle_config_update(message)
        elif message_type == 'status_request':
            return self._handle_status_request()
        else:
            return {"status": "error", "message": f"未知的消息类型: {message_type}"}
    
    def _handle_aim_request(self, message: Dict[str, Any]) -> Dict[str, Any]:
        """处理瞄准请求"""
        try:
            enemy_data = message.get('enemy_data', {})
            player_health = message.get('player_health', 100)
            took_damage = message.get('took_damage', False)
            
            is_aiming, aim_position = self.track_enemy_head(enemy_data, player_health, took_damage)
            
            return {
                "status": "success",
                "is_aiming": is_aiming,
                "aim_position": aim_position,
                "timestamp": time.time()
            }
        except Exception as e:
            return {"status": "error", "message": f"瞄准处理失败: {e}"}
    
    def _handle_config_update(self, message: Dict[str, Any]) -> Dict[str, Any]:
        """处理配置更新"""
        try:
            new_config = message.get('config', {})
            self.update_config(**new_config)
            return {
                "status": "success", 
                "message": "配置更新成功",
                "new_config": self.config.to_dict()
            }
        except Exception as e:
            return {"status": "error", "message": f"配置更新失败: {e}"}
    
    def _handle_status_request(self) -> Dict[str, Any]:
        """处理状态查询"""
        return {
            "status": "success",
            "system_status": {
                "is_active": self.is_active,
                "current_target": self.current_target,
                "config": self.config.to_dict(),
                "clients_connected": len(self.clients)
            }
        }
    
    def calculate_head_position(self, enemy_position: Tuple[float, float, float], 
                              enemy_height: float = 1.8) -> Tuple[float, float, float]:
        """计算敌人头部位置"""
        x, y, z = enemy_position
        head_x = x
        head_y = y + enemy_height * 0.9
        head_z = z
        return (head_x, head_y, head_z)
    
    def smooth_aim(self, current_aim: Tuple[float, float, float], 
                  target: Tuple[float, float, float]) -> Tuple[float, float, float]:
        """平滑瞄准函数"""
        current_x, current_y, current_z = current_aim
        target_x, target_y, target_z = target
        
        new_x = current_x + (target_x - current_x) * self.smooth_factor * (self.config.lock_strength / 100)
        new_y = current_y + (target_y - current_y) * self.smooth_factor * (self.config.lock_strength / 100)
        new_z = current_z + (target_z - current_z) * self.smooth_factor * (self.config.lock_strength / 100)
        
        return (new_x, new_y, new_z)
    
    def track_enemy_head(self, enemy_data: dict, player_health: int, 
                        took_damage: bool = False) -> Tuple[bool, Tuple[float, float, float]]:
        """追踪敌人头部主函数"""
        
        if not self.should_activate(player_health, took_damage):
            self.is_active = False
            return False, self.last_aim_position
        
        self.is_active = True
        
        head_position = self.calculate_head_position(enemy_data['position'])
        smoothed_aim = self.smooth_aim(self.last_aim_position, head_position)
        self.last_aim_position = smoothed_aim
        
        if self.config.aim_intensity < 100:
            randomness = (100 - self.config.aim_intensity) / 1000
            smoothed_aim = (
                smoothed_aim[0] + random.uniform(-randomness, randomness),
                smoothed_aim[1] + random.uniform(-randomness, randomness),
                smoothed_aim[2] + random.uniform(-randomness, randomness)
            )
        
        return True, smoothed_aim
    
    def should_activate(self, player_health: int, took_damage: bool = False) -> bool:
        """判断是否应该激活瞄准"""
        if player_health <= self.config.health_threshold:
            return False
        
        if self.config.continuous_activation and self.is_active:
            return True
            
        if self.config.damage_activation and took_damage:
            return True
            
        return self.config.continuous_activation
    
    def update_config(self, **kwargs):
        """动态更新配置"""
        for key, value in kwargs.items():
            if hasattr(self.config, key):
                setattr(self.config, key, value)
        
        if self.config.console_output:
            self.log(f"配置已更新 - 强度:{self.config.aim_intensity}%")

# 客户端类（用于测试和连接服务器）
class AimClient:
    """瞄准系统客户端"""
    
    def __init__(self, server_host: str = 'localhost', server_port: int = 8080):
        self.server_host = server_host
        self.server_port = server_port
    
    def send_request(self, message: Dict[str, Any]) -> Dict[str, Any]:
        """发送请求到服务器"""
        try:
            with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
                sock.settimeout(5.0)
                sock.connect((self.server_host, self.server_port))
                
                # 发送JSON数据
                sock.send(json.dumps(message).encode('utf-8'))
                
                # 接收响应
                response = sock.recv(4096).decode('utf-8')
                return json.loads(response)
                
        except Exception as e:
            return {"status": "error", "message": f"连接失败: {e}"}

# 服务器启动函数
def start_aim_server(port: int = 8080):
    """启动瞄准服务器"""
    config = AimConfig()
    aim_bot = SmoothAimBot(config, port)
    aim_bot.start_server()
    return aim_bot

# 使用示例
if __name__ == "__main__":
    # 启动服务器
    server = start_aim_server(8080)
    
    # 创建测试客户端
    client = AimClient('localhost', 8080)
    
    # 等待服务器启动
    time.sleep(2)
    
    # 测试瞄准请求
    test_enemy = {
        'name': '测试敌人',
        'position': (15.0, 2.5, 8.0)
    }
    
    aim_request = {
        'type': 'aim_request',
        'enemy_data': test_enemy,
        'player_health': 100,
        'took_damage': True
    }
    
    response = client.send_request(aim_request)
    print("服务器响应:", json.dumps(response, indent=2, ensure_ascii=False))
    
    # 保持服务器运行
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        server.stop_server()
        print("服务器已停止")