import numpy as np
from typing import List, Tuple
from dataclasses import dataclass
from enum import Enum
import time

class WeaponType(Enum):
    ASSAULT_RIFLE = 1
    SMG = 2
    SNIPER = 3
    SHOTGUN = 4
    PROJECTILE = 5

@dataclass
class Vector3:
    x: float = 0.0
    y: float = 0.0
    z: float = 0.0
    
    def __add__(self, other):
        return Vector3(self.x + other.x, self.y + other.y, self.z + other.z)
    
    def __sub__(self, other):
        return Vector3(self.x - other.x, self.y - other.y, self.z - other.z)
    
    def __mul__(self, scalar):
        return Vector3(self.x * scalar, self.y * scalar, self.z * scalar)
    
    def magnitude(self):
        return np.sqrt(self.x**2 + self.y**2 + self.z**2)
    
    def normalized(self):
        mag = self.magnitude()
        if mag == 0:
            return Vector3()
        return Vector3(self.x/mag, self.y/mag, self.z/mag)

@dataclass
class Target:
    position: Vector3
    velocity: Vector3
    acceleration: Vector3
    health: float
    is_attacking: bool
    is_facing: bool
    is_visible: bool
    threat_level: int
    target_id: int
    last_seen_time: float
    hitbox_size: float = 1.0

@dataclass
class PlayerState:
    position: Vector3
    velocity: Vector3
    is_moving: bool
    is_aiming: bool
    is_crouching: bool
    weapon_type: WeaponType
    ammo_count: int
    health: float
    stance_stability: float = 1.0

class EnhancedAimAssist:
    def __init__(self):
        # 配置参数
        self.MAX_DIST = 100.0
        self.ASSIST_THRESHOLD = 50.0
        self.MAX_STRENGTH = 0.8
        self.SWITCH_COOLDOWN = 0.3
        self.ASSIST_FACTOR = 0.15
        
        # 状态变量
        self.last_switch_time = 0.0
        self.last_target_id = -1
        self.target_history = {}
        self.smoothing_buffer = []
        self.current_strength = 0.0
        
        # 武器特定参数
        self.weapon_params = {
            WeaponType.ASSAULT_RIFLE: {"optimal_range": 30.0, "stability": 0.8},
            WeaponType.SMG: {"optimal_range": 15.0, "stability": 0.6},
            WeaponType.SNIPER: {"optimal_range": 80.0, "stability": 0.9},
            WeaponType.SHOTGUN: {"optimal_range": 8.0, "stability": 0.5},
            WeaponType.PROJECTILE: {"optimal_range": 20.0, "stability": 0.7}
        }
    
    def calculate_distance(self, a: Vector3, b: Vector3) -> float:
        """计算两点之间的距离"""
        return (a - b).magnitude()
    
    def calculate_priority_score(self, target: Target, current_aim: Vector3, 
                               player: PlayerState, delta_time: float) -> dict:
        """增强版优先级评分计算"""
        dist = self.calculate_distance(current_aim, target.position)
        
        # 因子1：智能距离权重（35%）
        weapon_params = self.weapon_params[player.weapon_type]
        optimal_range = weapon_params["optimal_range"]
        range_penalty = abs(dist - optimal_range) / optimal_range
        dist_score = max(0, 1 - dist/self.MAX_DIST - range_penalty*0.3) * 0.35
        
        # 因子2：多维度威胁评估（30%）
        threat_score = self.calculate_threat_level(target, player, dist) * 0.3
        
        # 因子3：战术价值评估（20%）
        tactical_score = self.calculate_tactical_value(target, player) * 0.2
        
        # 因子4：预测置信度（15%）
        prediction_score = self.calculate_prediction_confidence(target, delta_time) * 0.15
        
        total_score = dist_score + threat_score + tactical_score + prediction_score
        
        # 可见性惩罚
        if not target.is_visible:
            total_score *= 0.4
        
        return {
            'total_score': total_score,
            'distance': dist,
            'threat_level': threat_score / 0.3,
            'tactical_value': tactical_score / 0.2
        }
    
    def calculate_threat_level(self, target: Target, player: PlayerState, distance: float) -> float:
        """智能威胁等级计算"""
        threat = 0.0
        
        # 攻击行为威胁
        if target.is_attacking:
            threat += 0.4
        elif target.is_facing:
            threat += 0.2
        
        # 距离威胁系数（越近威胁越大）
        distance_threat = 1.0 - min(distance / 25.0, 1.0)
        threat += distance_threat * 0.3
        
        # 历史威胁记忆
        if target.target_id in self.target_history:
            history_threat = self.target_history[target.target_id].get('threat_level', 0.0)
            threat += history_threat * 0.3
        
        return min(threat, 1.0)
    
    def calculate_tactical_value(self, target: Target, player: PlayerState) -> float:
        """战术价值评估"""
        value = 0.0
        
        # 低血量目标优先
        if target.health < 0.3:
            value += 0.4
        elif target.health < 0.6:
            value += 0.2
        
        # 玩家低血量时防御性选择
        if player.health < 0.3:
            # 优先选择威胁最大的目标
            value += target.threat_level * 0.3
        
        # 弹药考虑
        if player.ammo_count < 10:
            # 低弹药时优先易命中的目标
            value += (1.0 - target.health) * 0.3
        
        return min(value, 1.0)
    
    def calculate_prediction_confidence(self, target: Target, delta_time: float) -> float:
        """预测置信度计算"""
        # 基于目标运动稳定性计算置信度
        speed = target.velocity.magnitude()
        acceleration = target.acceleration.magnitude()
        
        # 速度越稳定，预测越准确
        speed_stability = max(0, 1.0 - speed / 20.0)
        accel_stability = max(0, 1.0 - acceleration / 10.0)
        
        return (speed_stability * 0.6 + accel_stability * 0.4)
    
    def advanced_motion_prediction(self, target: Target, delta_time: float) -> Vector3:
        """高级运动轨迹预测"""
        # 基础速度预测
        base_prediction = target.position + target.velocity * delta_time
        
        # 加速度补偿
        acceleration_prediction = target.acceleration * (0.5 * delta_time ** 2)
        
        # 行为模式预测（简单实现）
        behavioral_prediction = self.predict_behavioral_movement(target, delta_time)
        
        # 综合预测位置
        final_prediction = base_prediction + acceleration_prediction + behavioral_prediction
        
        # 如果是投掷物武器，考虑重力
        if hasattr(self, 'is_projectile_weapon') and self.is_projectile_weapon():
            gravity = Vector3(0, -9.8, 0)
            final_prediction += gravity * (0.5 * delta_time ** 2)
        
        return final_prediction
    
    def predict_behavioral_movement(self, target: Target, delta_time: float) -> Vector3:
        """行为运动模式预测"""
        # 简单实现：根据历史运动趋势预测
        if target.target_id in self.target_history:
            history = self.target_history[target.target_id]
            # 使用平均加速度作为行为预测
            avg_accel = history.get('avg_acceleration', Vector3())
            return avg_accel * (0.3 * delta_time ** 2)
        return Vector3()
    
    def calculate_dynamic_strength(self, distance: float, player: PlayerState, target: Target) -> float:
        """动态辅助强度计算"""
        base_strength = max(0, 1 - distance / self.ASSIST_THRESHOLD)
        
        # 玩家状态影响
        stability = 1.0
        
        # 移动惩罚
        if player.is_moving:
            stability *= 0.6
            if player.is_crouching:
                stability *= 0.8  # 蹲伏移动减轻惩罚
        
        # 瞄准增强
        if player.is_aiming:
            stability *= 1.3
        
        # 武器稳定性
        weapon_stab = self.weapon_params[player.weapon_type]["stability"]
        stability *= weapon_stab
        
        # 玩家血量影响
        if player.health < 0.3:
            stability *= 1.1  # 低血量时增强辅助
        
        # 目标状态影响
        if target.health < 0.2:
            stability *= 1.2  # 低血量目标增强锁定
        
        final_strength = np.clip(base_strength * stability, 0, self.MAX_STRENGTH)
        
        # 平滑强度变化
        self.current_strength = self.lerp(self.current_strength, final_strength, 0.2)
        
        return self.current_strength
    
    def lerp(self, a: float, b: float, t: float) -> float:
        """线性插值"""
        return a + (b - a) * t
    
    def enhanced_aim_assist(self, targets: List[Target], current_aim: Vector3, 
                          player_state: PlayerState, delta_time: float) -> Vector3:
        """增强版辅助瞄准主函数"""
        if not targets:
            return current_aim
        
        # 计算每个目标的优先级
        scored_targets = []
        for target in targets:
            score_data = self.calculate_priority_score(target, current_aim, player_state, delta_time)
            scored_targets.append({
                'target': target,
                'score_data': score_data,
                'distance': score_data['distance']
            })
        
        # 选择最佳目标
        best_target_data = max(scored_targets, key=lambda x: x['score_data']['total_score'])
        best_target = best_target_data['target']
        best_dist = best_target_data['distance']
        
        # 冷却机制检查
        current_time = time.time()
        if current_time - self.last_switch_time < self.SWITCH_COOLDOWN:
            # 保持原目标，但可以更新历史数据
            if self.last_target_id != -1:
                for target_data in scored_targets:
                    if target_data['target'].target_id == self.last_target_id:
                        best_target = target_data['target']
                        best_dist = target_data['distance']
                        break
        else:
            self.last_switch_time = current_time
            self.last_target_id = best_target.target_id
        
        # 更新目标历史
        self.update_target_history(best_target, delta_time)
        
        # 计算动态辅助强度
        assist_strength = self.calculate_dynamic_strength(best_dist, player_state, best_target)
        
        # 高级运动预测
        predicted_position = self.advanced_motion_prediction(best_target, delta_time)
        
        # 计算辅助偏移
        aim_offset = (predicted_position - current_aim) * assist_strength * self.ASSIST_FACTOR
        
        # 应用平滑滤波
        smoothed_offset = self.apply_smoothing(aim_offset, delta_time)
        new_aim = current_aim + smoothed_offset
        
        return new_aim
    
    def apply_smoothing(self, offset: Vector3, delta_time: float) -> Vector3:
        """应用平滑滤波"""
        self.smoothing_buffer.append(offset)
        if len(self.smoothing_buffer) > 5:
            self.smoothing_buffer.pop(0)
        
        # 计算加权平均
        total_weight = 0
        smoothed = Vector3()
        for i, vec in enumerate(self.smoothing_buffer):
            weight = i + 1  # 越新的数据权重越大
            smoothed += vec * weight
            total_weight += weight
        
        if total_weight > 0:
            smoothed = smoothed * (1.0 / total_weight)
        
        return smoothed
    
    def update_target_history(self, target: Target, delta_time: float):
        """更新目标历史数据"""
        if target.target_id not in self.target_history:
            self.target_history[target.target_id] = {
                'last_seen': time.time(),
                'avg_acceleration': Vector3(),
                'threat_level': 0.0
            }
        
        history = self.target_history[target.target_id]
        history['last_seen'] = time.time()
        
        # 更新平均加速度
        alpha = 0.3  # 平滑因子
        history['avg_acceleration'] = (history['avg_acceleration'] * (1-alpha) + 
                                     target.acceleration * alpha)
        
        # 更新威胁等级
        history['threat_level'] = target.threat_level

# 使用示例
if __name__ == "__main__":
    # 创建辅助瞄准实例
    aim_assist = EnhancedAimAssist()
    
    # 创建测试数据
    player = PlayerState(
        position=Vector3(0, 0, 0),
        velocity=Vector3(0, 0, 0),
        is_moving=False,
        is_aiming=True,
        is_crouching=False,
        weapon_type=WeaponType.ASSAULT_RIFLE,
        ammo_count=30,
        health=1.0
  (0, 0, 0)
    new_aim = aim_assist.enhanced_aim_assist([target], current_aim, player, 0.016)
    
    print(f"Original aim: ({current_aim.x}, {current_aim.y}, {current_aim.z})")
    print(f"New aim: ({new_aim.x}, {new_aim.y}, {new_aim.z})")  )
    
    target = Target(
        position=Vector3(10, 0, 0),
        velocity=Vector3(2, 0, 0),
        acceleration=Vector3(0, 0, 0),
        health=0.5,
        is_attacking=True,
        is_facing=True,
        is_visible=True,
        threat_level=8,
        target_id=1,
        last_seen_time=time.time()
    )
    
    # 测试辅助瞄准
    current_aim = Vector3
    
    
    
    
    
     #使用增强思路请留我的名字<辞酱>
    