#define _USE_MATH_DEFINES  // 修复M_PI未定义问题，必须在cmath前
#include <vector>
#include <cmath>
#include <iostream>

enum class TargetPart { HEAD, BODY, LIMB };

// 修复：补充PlayerData结构体定义
struct PlayerData {
    float posX, posY, posZ;
    float aimInput;
    bool  isIndoor;
    bool  isMoving;
};

struct TargetData {
    int   targetID;
    float posX, posY, posZ;
    float headPosX, headPosY, headPosZ;
    float health;
    bool  isEnemy;
    bool  isKnocked;
    float moveSpeed;
    float moveDirX, moveDirY;
};

struct BulletTracerConfig {
    bool  enableTracer      = true;
    float maxSearchRadius   = 3000.f;
    float maxTurnAngle      = 180.f;
    float turnAcceleration  = 9999.f;
    float homingStrength    = 1.5f;
    float predictionTime    = 1.f;
    TargetPart aimPart      = TargetPart::HEAD;
};

struct Bullet {
    float posX, posY, posZ;
    float velX, velY, velZ;
    float speed;
    bool  active;
};

struct Vec3 {
    float x, y, z;
    Vec3 operator-(const Vec3& rhs) const { return {x - rhs.x, y - rhs.y, z - rhs.z}; }
    Vec3 operator+(const Vec3& rhs) const { return {x + rhs.x, y + rhs.y, z + rhs.z}; }
    Vec3 operator*(float s) const { return {x * s, y * s, z * s}; }
    float length() const { return std::sqrt(x*x + y*y + z*z); }
    Vec3 normalized() const { 
        float len = length(); 
        return len > 1e-6f ? Vec3{x/len, y/len, z/len} : Vec3{0,0,0};  // 加微小值避免除零
    }
};

static Vec3 Cross(const Vec3& a, const Vec3& b) {
    return {a.y*b.z - a.z*b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x};
}

static float Dot(const Vec3& a, const Vec3& b) {
    return a.x*b.x + a.y*b.y + a.z*b.z;
}

bool UpdateBulletHoming(Bullet& bullet,
                        const std::vector<TargetData>& targets,
                        const BulletTracerConfig& config) {
    if (!bullet.active) return false;

    Vec3 bulletPos{bullet.posX, bullet.posY, bullet.posZ};
    Vec3 bestTargetHead{};
    float bestScore = -1.f;
    const TargetData* bestTarget = nullptr;

    // 筛选最佳敌方目标
    for (const auto& t : targets) {
        if (!t.isEnemy || t.isKnocked) continue;
        Vec3 head{t.headPosX, t.headPosY, t.headPosZ};
        float dist = (head - bulletPos).length();
        if (dist > config.maxSearchRadius) continue;
        // 评分：距离越近、血量越低，优先级越高
        float score = (config.maxSearchRadius - dist) * 100.f + (120.f - t.health) * 10.f;
        if (score > bestScore) {
            bestScore = score;
            bestTargetHead = head;
            bestTarget = &t;
        }
    }

    // 无有效目标时，保持原方向飞行
    if (bestScore < 0 || !bestTarget) return true;

    // 预测目标位置（基于移动方向和速度）
    Vec3 targetVel{bestTarget->moveDirX * bestTarget->moveSpeed,
                   bestTarget->moveDirY * bestTarget->moveSpeed, 0.f};
    Vec3 predictedHead = bestTargetHead + targetVel * config.predictionTime;

    // 计算期望方向和当前方向
    Vec3 desiredDir = (predictedHead - bulletPos).normalized();
    Vec3 currentDir{bullet.velX, bullet.velY, bullet.velZ};
    currentDir = currentDir.normalized();

    // 计算转向角度（限制在maxTurnAngle内）
    float angleRad = std::acos(std::fmax(-1.f, std::fmin(1.f, Dot(currentDir, desiredDir))));
    float angleDeg = angleRad * 180.f / static_cast<float>(M_PI);
    float clampedAngle = std::fmin(angleDeg, config.maxTurnAngle) * static_cast<float>(M_PI) / 180.f;

    // 计算转向轴（避免轴为零向量）
    Vec3 axis = Cross(currentDir, desiredDir);
    if (axis.length() < 1e-6f) axis = {0, 0, 1};  // 无转向时默认绕Z轴
    axis = axis.normalized();

    // 优化：确保转向角度不超过配置上限
    float newAngleRad = std::fmin(clampedAngle, clampedAngle * config.homingStrength);
    // 旋转当前方向到期望方向（球面线性插值简化）
    Vec3 newDir = currentDir * std::cos(newAngleRad) + Cross(axis, currentDir) * std::sin(newAngleRad);
    newDir = newDir.normalized();

    // 更新子弹速度（保持飞行速度不变）
    bullet.velX = newDir.x * bullet.speed;
    bullet.velY = newDir.y * bullet.speed;
    bullet.velZ = newDir.z * bullet.speed;

    return true;
}

void StepBullet(Bullet& bullet, float deltaTime) {
    if (!bullet.active) return;
    // 更新子弹位置（基于速度和时间增量）
    bullet.posX += bullet.velX * deltaTime;
    bullet.posY += bullet.velY * deltaTime;
    bullet.posZ += bullet.velZ * deltaTime;
    // Z轴超出范围时，标记子弹失效
    if (bullet.posZ < -500.f || bullet.posZ > 2000.f) bullet.active = false;
}

int main() {
    // 初始化玩家（仅用位置，其他字段默认）
    PlayerData player{0.f, 0.f, 10.f};
    // 初始化1个敌方目标（在(1500,800,5)，头部在(1500,800,8)，向斜上方移动）
    std::vector<TargetData> targets = {
        {201, 1500.f, 800.f, 5.f, 1500.f, 800.f, 8.f, 
         100.f, true, false, 15.f, 0.8f, 0.6f}
    };
    // 追踪配置（默认追踪头部，预测1秒后位置）
    BulletTracerConfig config{};
    // 初始化子弹（从玩家位置出发，初始向上飞）
    Bullet bullet{player.posX, player.posY, player.posZ, 
                  0.f, 0.f, 900.f, 900.f, true};

    const float dt = 0.016f;  // 约60帧/秒的时间增量
    // 模拟300帧（约4.8秒）的飞行
    for (int i = 0; i < 300; ++i) {
        UpdateBulletHoming(bullet, targets, config);
        StepBullet(bullet, dt);
        if (!bullet.active) break;
        // 每30帧打印一次状态（约0.48秒）
        if (i % 30 == 0) {
            std::printf("t=%.2f  bullet_pos(%.1f,%.1f,%.1f)  bullet_vel(%.1f,%.1f,%.1f)\n",
                        i * dt, bullet.posX, bullet.posY, bullet.posZ,
                        bullet.velX, bullet.velY, bullet.velZ);
        }
    }

    std::cout << "Bullet simulation done." << std::endl;
    return 0;
}
