#include <Windows.h>
#include <winternl.h>
#include <timeapi.h>
#pragma comment(lib, "winmm.lib")
#include <vector>
#include <thread>
#include <mutex>
#include <time.h>
#include <fstream>
#include <conio.h>
#include <stdarg.h>
#include "driver/driver_interface_v3.h"
#include "memory/memory_reader.h"
#include "memory/offsets.h"
#include "game/entity.h"
#include "game/math.h"
#include "OS-ImGui/OS-ImGui.h"
#include "security/polym.h"
#include "security/protec.h"
#include "security/license.h"

#include "game/feature_manager.h"
#include "game/triggerbot.h"
#include "game/esp_feature.h"
#include "game/distance_manager.h"
#include "game/aimbot.h"
#include <random>

DriverInterfaceV3* g_Driver = nullptr;
Overlay* g_Overlay = nullptr;
DWORD g_ApexPid = 0;
uintptr_t g_ApexBase = 0;

FeatureManager* g_FeatureManager = nullptr;

Aimbot* g_Aimbot = nullptr;
TriggerBot* g_TriggerBot = nullptr;
ESPFeature* g_ESP = nullptr;
DistanceManager* g_DistanceManager = nullptr;

bool g_IsInFiringRange = false;

std::vector<Entity> g_Entities;
std::mutex g_EntityMutex;
Vector3 g_LocalPos;
uintptr_t g_LocalPlayerAddress = 0;
int g_LocalTeam = 0;
Matrix g_ViewMatrix;
bool g_IsRunning = true;

Vector3 g_PunchAngles;

float g_ClosestEnemyDistance = 999999.0f;
int g_AdaptiveSleepTime = 33;

float g_ProjectileSpeed = 30000.0f;
float g_ProjectileScale = 1.0f;

Vector2 g_ScreenSize = { 1920, 1080 };

bool g_ShowMenu = false;

bool g_TestMouseEnabled = false;
std::atomic_bool g_TestMouseRunning(false);
std::thread g_TestMouseThread;

int g_TargetFPS = 30;
int g_SleepTime = 33;   




void SecurityWatchdog() {
    
    while (g_IsRunning) {
        Sleep(5000);
    }
}


void ProcessSettingsHotkeys() {
    
}

bool InitializeDriver() {
    g_Driver = new DriverInterfaceV3();
    if (!g_Driver->Initialize()) {
        delete g_Driver;
        g_Driver = nullptr;
        return false;
    }
    
    
    
    g_Driver->SetMouseSignature(0, 0);
    
    return true;
}

bool WaitForApex() {
    const char* dots[] = { ".", "..", "...", ".", "..", "..." };
    int dotIndex = 0;
    
    const wchar_t* processName = L"r5apex_dx12.exe";
    
    while (true) {
        g_ApexPid = g_Driver->GetProcessId(processName);
        if (g_ApexPid) break;
        
        
        printf("\r  [*] Waiting for Apex%s   ", dots[dotIndex]);
        fflush(stdout);
        dotIndex = (dotIndex + 1) % 6;
        
        Sleep(500);
    }
    printf("\r   Apex Found! PID: %d              \n", g_ApexPid);
    
    g_Driver->SetCurrentPid(g_ApexPid);
    return true;
}

bool GetModuleBase() {
    const wchar_t* moduleName = L"r5apex_dx12.exe";
    
    g_ApexBase = g_Driver->GetModuleBase(g_ApexPid, moduleName);
    
    if (!g_ApexBase || g_ApexBase < 0x10000) {
        return false;
    }
    
    g_Driver->GetProcessCr3(g_ApexPid);
    return true;
}

bool InitializeFeatures() {
    g_FeatureManager = new FeatureManager();
    
    g_Overlay = new Overlay();

    g_ESP = new ESPFeature();
    g_FeatureManager->RegisterFeature("f1", g_ESP, 0);
    
    g_DistanceManager = new DistanceManager();
    g_FeatureManager->RegisterFeature("f2", g_DistanceManager, 0);
    
    g_TriggerBot = new TriggerBot(g_Driver, g_Overlay);
    g_FeatureManager->RegisterFeature("f3", g_TriggerBot, 0);

    g_Aimbot = new Aimbot(g_Driver);
    g_FeatureManager->RegisterFeature("f4", g_Aimbot, 0);
    
    return true;
}

Vector3 GetLocalPlayerPosition() {
    uintptr_t localPlayer = Read<uintptr_t>(g_ApexBase + OFF_LOCAL_PLAYER);
    if (!localPlayer) return Vector3();
    return Read<Vector3>(localPlayer + OFF_LOCAL_ORIGIN);
}

int GetLocalPlayerTeam() {
    uintptr_t localPlayer = Read<uintptr_t>(g_ApexBase + OFF_LOCAL_PLAYER);
    if (!localPlayer) return 0;
    return Read<int>(localPlayer + OFF_TEAM_NUMBER);
}

void UpdateWeaponInfo() {
    uintptr_t localPlayer = Read<uintptr_t>(g_ApexBase + OFF_LOCAL_PLAYER);
    if (!localPlayer) return;
    
    
    uintptr_t weaponHandle = Read<uintptr_t>(localPlayer + OFF_WEAPON_HANDLE);
    if (!weaponHandle || weaponHandle == 0xFFFFFFFF) {
        g_ProjectileSpeed = 30000.0f; 
        g_ProjectileScale = 1.0f;
        return;
    }
    
    
    uintptr_t weaponEntity = Read<uintptr_t>(g_ApexBase + OFF_ENTITY_LIST + ((weaponHandle & 0xFFFF) << 5));
    if (!weaponEntity) {
        g_ProjectileSpeed = 30000.0f;
        g_ProjectileScale = 1.0f;
        return;
    }
    
    
    g_ProjectileSpeed = Read<float>(weaponEntity + OFF_PROJECTILESPEED);
    g_ProjectileScale = Read<float>(weaponEntity + OFF_PROJECTILESCALE);
    
    
    if (g_ProjectileSpeed <= 0 || g_ProjectileSpeed > 100000.0f) {
        g_ProjectileSpeed = 30000.0f;
    }
    if (g_ProjectileScale <= 0 || g_ProjectileScale > 10.0f) {
        g_ProjectileScale = 1.0f;
    }
}

Matrix GetViewMatrix() {
    static uintptr_t cachedViewRender = 0;
    static uintptr_t cachedViewMatrixPtr = 0;
    static ULONGLONG lastPtrUpdate = 0;
    ULONGLONG now = GetTickCount64();

    // 每 5 秒更新一次指针，或者如果尚未获取
    if (now - lastPtrUpdate > 5000 || !cachedViewRender || !cachedViewMatrixPtr) {
        cachedViewRender = Read<uintptr_t>(g_ApexBase + OFF_VIEWRENDER);
        if (cachedViewRender) {
            cachedViewMatrixPtr = Read<uintptr_t>(cachedViewRender + OFF_VIEWMATRIX);
        }
        lastPtrUpdate = now;
    }

    if (!cachedViewMatrixPtr) return Matrix();
    
    Matrix m;
    if (!g_Driver->ReadMemory(g_ApexPid, cachedViewMatrixPtr, &m, sizeof(Matrix))) {
        // 如果读取失败，强制下一次更新指针
        cachedViewMatrixPtr = 0;
        return Matrix();
    }
    return m;
}


void MemoryLoop() {
    
    
    
    
    int loopCounter = 0;
    
    while (g_IsRunning) {
        
        
        if (++loopCounter >= 1000) {
            loopCounter = 0;
            if (!RuntimeSync::UpdateRuntimeState()) {
                
                g_IsRunning = false;
                ExitProcess(0);
            }
        }
        
        if (g_ApexBase != 0) {
            uintptr_t localPlayer = 0;
            
            try {
                
                // 检查是否需要更新 CR3 (应对 CR3 Shuffle)
                static ULONGLONG lastCr3Update = 0;
                ULONGLONG now = GetTickCount64();
                if (now - lastCr3Update > 30000) { // 每 30 秒更新一次
                    g_Driver->UpdateCr3();
                    lastCr3Update = now;
                }

                localPlayer = Read<uintptr_t>(g_ApexBase + OFF_LOCAL_PLAYER);
                
                
                if (!localPlayer || localPlayer < 0x10000 || localPlayer > 0x7FFFFFFFFFFF) {
                    Sleep(g_AdaptiveSleepTime);
                    continue;
                }
                
                
                // 优化：批量读取本地玩家基本数据
                uint8_t localBuffer[0x5000]; // 增加大小以覆盖所有必要偏移 (包括 OFF_ARMORTYPE 0x48f4)
                if (!g_Driver->ReadMemory(g_ApexPid, localPlayer, localBuffer, sizeof(localBuffer))) {
                    Sleep(g_AdaptiveSleepTime);
                    continue;
                }

                Vector3 localPos = *(Vector3*)(localBuffer + OFF_LOCAL_ORIGIN);
                int localTeam = *(int*)(localBuffer + OFF_TEAM_NUMBER);
                Vector3 punch = *(Vector3*)(localBuffer + OFF_PUNCH_ANGLES);
                int localArmorType = *(int*)(localBuffer + OFF_ARMORTYPE);

                if (localPos.x == 0 && localPos.y == 0 && localPos.z == 0) {
                    Sleep(g_AdaptiveSleepTime);
                    continue; 
                }
                
                if (localTeam < 0 || localTeam > 255) {
                    Sleep(g_AdaptiveSleepTime);
                    continue; 
                }
                
                // 检查是否在训练场
                  char levelName[64];
                  if (g_Driver->ReadMemory(g_ApexPid, g_ApexBase + OFF_LEVEL, levelName, sizeof(levelName))) {
                      levelName[63] = '\0';
                      
                      char* finalLevelName = levelName;
                      
                      // 检查第一个字符是否为打印字符。如果是，说明这可能就是字符串本身
                      // 如果不是，且看起来像一个 64 位地址，则尝试作为指针读取
                      if (levelName[0] < 32 || levelName[0] > 126) {
                          uint64_t levelPtr = *(uint64_t*)levelName;
                          if (levelPtr > 0x10000 && levelPtr < 0x7FFFFFFFFFFF) {
                              if (g_Driver->ReadMemory(g_ApexPid, levelPtr, levelName, sizeof(levelName))) {
                                  levelName[63] = '\0';
                                  finalLevelName = levelName;
                              }
                          }
                      }

                      if (strstr(finalLevelName, "firing_range") || strstr(finalLevelName, "mp_rr_party_crasher")) {
                          g_IsInFiringRange = true;
                      } else {
                          g_IsInFiringRange = false;
                      }
                  }

                Matrix viewMatrix = GetViewMatrix();

                // 优化：使用已读取的 buffer 更新武器信息
                uint32_t weaponHandle = *(uint32_t*)(localBuffer + OFF_WEAPON_HANDLE);
                if (weaponHandle != 0 && weaponHandle != 0xFFFFFFFF) {
                    uintptr_t weaponEntity = 0;
                    // 直接从 entity pointers 数组或通过 entity list 读取
                    if (g_Driver->ReadMemory(g_ApexPid, g_ApexBase + OFF_ENTITY_LIST + ((weaponHandle & 0xFFFF) << 5), &weaponEntity, sizeof(weaponEntity))) {
                        if (weaponEntity > 0x10000) {
                            g_Driver->ReadMemory(g_ApexPid, weaponEntity + OFF_PROJECTILESPEED, &g_ProjectileSpeed, sizeof(float));
                            g_Driver->ReadMemory(g_ApexPid, weaponEntity + OFF_PROJECTILESCALE, &g_ProjectileScale, sizeof(float));
                        }
                    }
                }
                
                auto entities = EntityScanner::ScanEntities(256);
                
                // 更新杂项功能 (如武器发光、隐藏武器)
                
                float closestDist = 999999.0f;
                for (auto& ent : entities) {
                    if (ent.valid && ent.team != localTeam) {
                        ent.CalculateDistance(localPos);
                        if (ent.distance < closestDist) {
                            closestDist = ent.distance;
                        }
                    }
                }
                
                
                float closestMeters = closestDist / 39.37f;
                g_ClosestEnemyDistance = closestMeters;
                
                
                
                
                
                
                if (closestMeters < 60.0f) {
                    g_AdaptiveSleepTime = 10;  // 即使极近也保持 10ms 间隔，防止 I/O 饱和
                } else if (closestMeters < 150.0f) {
                    g_AdaptiveSleepTime = 20;  
                } else {
                    g_AdaptiveSleepTime = 40;  
                }
                
                
                {
                    std::lock_guard<std::mutex> lock(g_EntityMutex);
                    g_LocalPos = localPos;
                    g_LocalPlayerAddress = localPlayer;
                    g_LocalTeam = localTeam;
                    g_ViewMatrix = viewMatrix;
                    g_PunchAngles = punch;
                    g_Entities = entities;
                }
                
                
                if (g_FeatureManager && localPlayer) {
                    g_FeatureManager->UpdateAllFeatures(localPlayer, g_ApexBase);
                }
            } catch (...) {
                
                
            }
        }
        
        
        TimeHelper::SleepFor(g_AdaptiveSleepTime, 5);
    }
}


void RenderMenu() {
    if (!g_ShowMenu) return;
    
    
    static int activeTab = 0;
    
    ImGuiStyle* style = &ImGui::GetStyle();
    
    
    ImVec4 originalSeparator = style->Colors[ImGuiCol_Separator];
    ImVec4 originalBorder = style->Colors[ImGuiCol_Border];
    ImVec2 originalItemSpacing = style->ItemSpacing;
    ImVec2 originalFramePadding = style->FramePadding;
    float originalFrameBorderSize = style->FrameBorderSize;
    
    
    style->WindowPadding = ImVec2(6, 6);
    style->Colors[ImGuiCol_Separator] = ImVec4(0, 0, 0, 0); 
    style->Colors[ImGuiCol_Border] = ImVec4(0, 0, 0, 0);    
    style->FrameBorderSize = 0.0f;                           
    
    
    ImVec4 bg_color = ImVec4(10.0f / 255.0f, 10.0f / 255.0f, 10.0f / 255.0f, 1.00f);
    ImVec4 button_color = ImVec4(12.f/255.f, 12.f/255.f, 12.f/255.f, 1.0f);
    ImVec4 button_hover = ImVec4(22.f/255.f, 22.f/255.f, 22.f/255.f, 1.0f);
    ImVec4 button_active = ImVec4(20.f/255.f, 20.f/255.f, 20.f/255.f, 1.0f);
    
        
        ImGui::SetNextWindowSize(ImVec2(580.f, 480.f));
        if (ImGui::Begin("##m", 0, ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse | ImGuiWindowFlags_NoTitleBar)) {        ImGui::BeginChild("Complete Border", ImVec2(568.f, 468.f), false);
        {
            ImVec2 window_pos = ImGui::GetWindowPos();
            ImVec2 window_size = ImGui::GetWindowSize();
            ImVec2 image_size = ImVec2(568.f, 468.f);
            ImVec2 image_pos;
            image_pos.x = window_pos.x + (window_size.x - image_size.x) * 0.5f;
            image_pos.y = window_pos.y + (window_size.y - image_size.y) * 0.5f;
            
            
            ImGui::GetWindowDrawList()->AddRectFilled(image_pos, 
                ImVec2(image_pos.x + image_size.x, image_pos.y + image_size.y), 
                IM_COL32(10, 10, 10, 255));
        }
        ImGui::EndChild();
        
        ImGui::SameLine(6.f);
        
        style->Colors[ImGuiCol_ChildBg] = ImColor(0, 0, 0, 0);
        style->ItemSpacing = ImVec2(0.f, 0.f);

        ImGui::BeginChild("Menu", ImVec2(568.f, 468.f), false);
        {
            ImGui::Columns(2, nullptr, false); 
            ImGui::SetColumnWidth(0, 64.f);
            style->ItemSpacing = ImVec2(0.f, -1.f);
            
            ImDrawList* draw_list = ImGui::GetWindowDrawList();
            ImVec2 pos = ImGui::GetCursorScreenPos();
            ImVec2 size = ImVec2(64, 468.f);
            
            
            ImU32 color = IM_COL32(12, 12, 12, 255);
            ImVec2 shifted_pos = ImVec2(pos.x, pos.y + 1);
            draw_list->AddRectFilled(shifted_pos, ImVec2(shifted_pos.x + size.x, shifted_pos.y + size.y), color);
            
            ImVec2 cursor_pos = ImGui::GetCursorPos();
            
            
            ImGui::PushStyleVar(ImGuiStyleVar_FrameRounding, 0.0f);
            ImGui::PushStyleVar(ImGuiStyleVar_FrameBorderSize, 0.0f); 
            ImGui::PushStyleColor(ImGuiCol_Button, button_color);
            ImGui::PushStyleColor(ImGuiCol_ButtonHovered, button_hover);
            ImGui::PushStyleColor(ImGuiCol_ButtonActive, button_active);
            ImGui::PushStyleColor(ImGuiCol_Border, ImVec4(0, 0, 0, 0)); 
            
            
            if (ImGui::GetIO().Fonts->Fonts.Size > 2) {
                ImGui::PushFont(ImGui::GetIO().Fonts->Fonts[2]);
            }
            
            
            {
                ImVec2 btn_pos = cursor_pos;
                btn_pos.y += 2;
                btn_pos.x -= 2;
                ImGui::SetCursorPos(btn_pos);
                if (ImGui::Button("V", ImVec2(64.f, 56.f))) activeTab = 0;
            }
            
        
            
            
            {
                ImVec2 btn_pos = cursor_pos;
                btn_pos.y += 120;
                btn_pos.x -= 2;
                ImGui::SetCursorPos(btn_pos);
                if (ImGui::Button("A", ImVec2(64.f, 56.f))) activeTab = 2;
            }

            
            {
                ImVec2 btn_pos = cursor_pos;
                btn_pos.y += 180;
                btn_pos.x -= 2;
                ImGui::SetCursorPos(btn_pos);
                if (ImGui::Button("T", ImVec2(64.f, 56.f))) activeTab = 3;
            }
            
            
            {
                ImVec2 btn_pos = cursor_pos;
                btn_pos.y += 240;
                btn_pos.x -= 2;
                ImGui::SetCursorPos(btn_pos);
                if (ImGui::Button("S", ImVec2(64.f, 56.f))) activeTab = 4;
            }
            
            if (ImGui::GetIO().Fonts->Fonts.Size > 2) {
                ImGui::PopFont();
            }
            ImGui::PopStyleColor(4); 
            ImGui::PopStyleVar(2);    
            
            ImGui::NextColumn();
            
            
            ImGui::BeginChild("MainContent");
            {
                style->ItemSpacing = ImVec2(6, 4); 
                style->FramePadding = ImVec2(6, 3);
                
                if (activeTab == 0) 
                {
                    ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
                    ImGui::Text(u8"视觉");
                    ImGui::PopStyleColor();
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    
                    if (g_ESP) {
                        bool espEnabled = g_ESP->IsEnabled();
                        ImGui::Text(u8"透视状态");
                        if (ImGui::Checkbox("##espenable", &espEnabled)) {
                            g_ESP->SetEnabled(espEnabled);
                        }
                        ImGui::SameLine();
                        ImGui::Text(espEnabled ? u8"已开启" : u8"已关闭");
                    }
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    
                    ImGui::Text(u8"最大距离");
                    static int maxDistance = 500;
                    if (g_DistanceManager) {
                        maxDistance = (int)g_DistanceManager->GetMaxDistance();
                    }
                    if (ImGui::SliderInt("##maxdist", &maxDistance, 100, 1000, u8"%d米")) {
                        if (g_DistanceManager) {
                            g_DistanceManager->SetMaxDistance((float)maxDistance);
                        }
                    }
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    
                    ImGui::Text(u8"透视功能");
                    ImGui::Spacing();
                    
                    if (g_ESP) {
                        ImGui::Checkbox(u8"方框透视", &g_ESP->config.showBoxes);
            ImGui::Checkbox(u8"骨骼显示", &g_ESP->config.showSkeleton);
            ImGui::Checkbox(u8"天线显示", &g_ESP->config.showAntenna);
            ImGui::Checkbox(u8"仅显示可见目标", &g_ESP->config.onlyShowVisible);
                        if (g_ESP->config.showSkeleton) {
                            ImGui::SameLine();
                            ImGui::SetNextItemWidth(100);
                            ImGui::SliderFloat(u8"粗细##skel", &g_ESP->config.skeletonThickness, 1.0f, 5.0f, "%.1f");
                        }
                        ImGui::Checkbox(u8"血量显示", &g_ESP->config.showHealthBars);
                        ImGui::Checkbox(u8"护甲显示", &g_ESP->config.showShieldBars);
                        ImGui::Checkbox(u8"距离显示", &g_ESP->config.showDistances);
                        ImGui::Checkbox(u8"击倒显示", &g_ESP->config.showKnocked);
                    }
                }
                else if (activeTab == 1) 
                {
                    ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
                    ImGui::Text(u8"杂项");
                    ImGui::PopStyleColor();
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    ImGui::Text(u8"状态");
                    ImGui::Spacing();
                    ImGui::BulletText(u8"驱动已连接");
                    ImGui::BulletText(u8"游戏: %s", g_ApexBase ? u8"Apex 英雄" : u8"等待中...");

                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();

                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    ImGui::Text(u8"按键测试");
                    ImGui::Text(u8"ALT (按住) - 随机移动鼠标");
                    ImGui::Checkbox(u8"开启 ALT 测试", &g_TestMouseEnabled);
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    ImGui::Text(u8"信息");
                    ImGui::Spacing();
                    ImGui::BulletText("v10.0");
                    ImGui::BulletText("SP");
                    ImGui::BulletText("OK");
                }
                else if (activeTab == 2) 
                {
                    ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
                    ImGui::Text(u8"自瞄");
                    ImGui::PopStyleColor();
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    if (g_Aimbot) {
                        g_Aimbot->RenderMenu();
                    }
                }
                else if (activeTab == 3) 
                {
                    ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
                    ImGui::Text(u8"扳机");
                    ImGui::PopStyleColor();
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    if (g_TriggerBot) {
                        g_TriggerBot->RenderMenu();
                    }
                }
                else if (activeTab == 4) 
                {
                    ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(0.8f, 0.8f, 0.8f, 1.0f));
                    ImGui::Text(u8"设置");
                    ImGui::PopStyleColor();
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    ImGui::Text(u8"性能");
                    ImGui::SliderInt(u8"基础帧率", &g_TargetFPS, 30, 240);
                    
                    
                    ImGui::Text(u8"自适应时序:");
                    ImGui::BulletText(u8"最近敌人: %.0f米", g_ClosestEnemyDistance);
                    ImGui::BulletText(u8"当前频率: %dms", g_AdaptiveSleepTime);
                    
                    ImGui::Spacing();
                    ImGui::Separator();
                    ImGui::Spacing();
                    
                    ImGui::Text(u8"覆盖层信息");
                    ImGui::Spacing();
                    ImGui::BulletText(u8"帧率: %.1f", ImGui::GetIO().Framerate);
                    ImGui::BulletText(u8"菜单热键: HOME");
                }
            }
            ImGui::EndChild();
            
            ImGui::Columns(1);
        }
        ImGui::EndChild();
    }
    ImGui::End();
    
    
    style->Colors[ImGuiCol_Separator] = originalSeparator;
    style->Colors[ImGuiCol_Border] = originalBorder;
    style->ItemSpacing = originalItemSpacing;
    style->FramePadding = originalFramePadding;
    style->FrameBorderSize = originalFrameBorderSize;
}


void RenderESP() {
    
    try {
        
        g_ScreenSize.x = ImGui::GetIO().DisplaySize.x;
        g_ScreenSize.y = ImGui::GetIO().DisplaySize.y;
        
        
        static bool homeKeyWasPressed = false;
        bool homeKeyIsPressed = (GetAsyncKeyState(VK_HOME) & 0x8000) != 0;
        
        if (homeKeyIsPressed && !homeKeyWasPressed) {
            g_ShowMenu = !g_ShowMenu;
        }
        homeKeyWasPressed = homeKeyIsPressed;

        
        if (g_TestMouseEnabled && g_Driver) {
            bool altDown = (GetAsyncKeyState(VK_MENU) & 0x8000) != 0; 

            if (altDown && !g_TestMouseRunning.load(std::memory_order_relaxed)) {
                g_TestMouseRunning.store(true, std::memory_order_relaxed);
                if (!g_TestMouseThread.joinable()) {
                    g_TestMouseThread = std::thread([] {
                        g_Driver->TestRandomMouseMoveLoop(g_TestMouseRunning);
                    });
                }
            } else if (!altDown && g_TestMouseRunning.load(std::memory_order_relaxed)) {
                g_TestMouseRunning.store(false, std::memory_order_relaxed);
                if (g_TestMouseThread.joinable()) {
                    g_TestMouseThread.join();
                }
            }
        } else if (!g_TestMouseEnabled && g_TestMouseRunning.load(std::memory_order_relaxed)) {
            
            g_TestMouseRunning.store(false, std::memory_order_relaxed);
            if (g_TestMouseThread.joinable()) {
                g_TestMouseThread.join();
            }
        }
        
        
        RenderMenu();
        
        if (g_ApexBase == 0) return;
        
        
        std::vector<Entity> entities;
        Vector3 localPos;
        int localTeam;
        Matrix viewMatrix;
        
        {
            std::lock_guard<std::mutex> lock(g_EntityMutex);
            entities = g_Entities;
            localPos = g_LocalPos;
            localTeam = g_LocalTeam;
            viewMatrix = g_ViewMatrix;
        }
        
        
        if (localPos.x == 0 && localPos.y == 0 && localPos.z == 0) {
            return; 
        }
    
        
        if (g_ESP && g_ESP->IsEnabled()) {
            ImDrawList* drawList = ImGui::GetBackgroundDrawList();
            
            
            float maxDistanceMeters = g_DistanceManager ? g_DistanceManager->GetMaxDistance() : 500.0f;
            float maxDistanceInches = maxDistanceMeters * 39.37f; 
            
            for (auto& entity : entities) {
                if (!entity.IsValidForESP(localPos, localTeam, maxDistanceInches))
                    continue;
                
                // 可见性过滤
                if (g_ESP->config.onlyShowVisible && !entity.isVisible)
                    continue;
                Vector2 head = WorldToScreen(entity.position + Vector3(0, 0, 70), viewMatrix, g_ScreenSize.x, g_ScreenSize.y);
                Vector2 feet = WorldToScreen(entity.position, viewMatrix, g_ScreenSize.x, g_ScreenSize.y);
                
                // 恢复安全的有效性检查，但增加一定的溢出容差（允许部分出屏）
                auto IsPartiallyVisible = [&](const Vector2& v) {
                    return v.x > -500.0f && v.x < (g_ScreenSize.x + 500.0f) && 
                           v.y > -500.0f && v.y < (g_ScreenSize.y + 500.0f);
                };

                if (!IsPartiallyVisible(head) && !IsPartiallyVisible(feet)) {
                    continue;
                }
                
                float height = feet.y - head.y;
                float width = height / 2.0f;
                float x = feet.x - width / 2.0f;
                float y = head.y;
                
                ImVec2 topLeft(x, y);
                ImVec2 bottomRight(x + width, y + height);
                
                
                // --- 计算颜色 ---
                ImU32 boxColor;
                auto& cfg = g_ESP->config;
                
                if (entity.isVisible) {
                    boxColor = ImGui::ColorConvertFloat4ToU32(cfg.visibleColor);
                } else if (entity.isDummy) {
                    boxColor = ImGui::ColorConvertFloat4ToU32(cfg.dummyColor);
                } else if (entity.isKnocked) {
                    boxColor = ImGui::ColorConvertFloat4ToU32(cfg.knockedColor);
                } else {
                    boxColor = ImGui::ColorConvertFloat4ToU32(cfg.enemyColor);
                }
                
                
                // --- 绘制方框 ---
                if (g_ESP->config.showBoxes) {
                    float thickness = g_ESP->config.boxThickness;
                    float outlineThickness = thickness + 1.5f;
                    ImU32 outlineColor = IM_COL32(0, 0, 0, 200);

                    // 绘制背景填充（非常浅的黑色透明层）
                    drawList->AddRectFilled(topLeft, bottomRight, IM_COL32(0, 0, 0, 40));

                    // 绘制四个角（带黑色描边）
                    float lineW = width / 4.0f;
                    float lineH = height / 4.0f;

                    auto DrawCorner = [&](ImVec2 p1, ImVec2 p2, ImVec2 p3) {
                        drawList->AddLine(p1, p2, outlineColor, outlineThickness);
                        drawList->AddLine(p1, p3, outlineColor, outlineThickness);
                        drawList->AddLine(p1, p2, boxColor, thickness);
                        drawList->AddLine(p1, p3, boxColor, thickness);
                    };

                    // 左上
                    DrawCorner(topLeft, ImVec2(topLeft.x + lineW, topLeft.y), ImVec2(topLeft.x, topLeft.y + lineH));
                    // 右上
                    DrawCorner(ImVec2(bottomRight.x, topLeft.y), ImVec2(bottomRight.x - lineW, topLeft.y), ImVec2(bottomRight.x, topLeft.y + lineH));
                    // 左下
                    DrawCorner(ImVec2(topLeft.x, bottomRight.y), ImVec2(topLeft.x + lineW, bottomRight.y), ImVec2(topLeft.x, bottomRight.y - lineH));
                    // 右下
                    DrawCorner(bottomRight, ImVec2(bottomRight.x - lineW, bottomRight.y), ImVec2(bottomRight.x, bottomRight.y - lineH));
                }

                // --- 绘制天线 ---
                if (g_ESP->config.showAntenna) {
                    Vector3 antennaWorldTop = entity.position + Vector3(0, 0, 100); // 稍微降低一点高度
                    Vector2 antennaTop = WorldToScreen(antennaWorldTop, viewMatrix, g_ScreenSize.x, g_ScreenSize.y);
                    
                    // 恢复较为严格但带容差的检查
                    bool isAntennaValid = antennaTop.x > -100.0f && antennaTop.y > -100.0f && 
                                         antennaTop.x < (g_ScreenSize.x + 100.0f) && 
                                         antennaTop.y < (g_ScreenSize.y + 100.0f);
                    
                    // 另外检查它是否离头部的点太远（防止瞬间拉伸到异常点）
                    float distToHead = sqrtf(powf(antennaTop.x - head.x, 2) + powf(antennaTop.y - head.y, 2));
                    
                    if (isAntennaValid && distToHead < (height * 3.0f) && distToHead > 1.0f) {
                        drawList->AddLine(ImVec2(head.x, head.y), ImVec2(antennaTop.x, antennaTop.y), boxColor, 1.0f);
                    }
                }

                // --- 绘制骨骼 ---
                if (g_ESP->config.showSkeleton) {
                    g_ESP->DrawSkeleton(drawList, entity, viewMatrix, boxColor, g_ESP->config.skeletonThickness);
                }
                
                // --- 绘制血条/护甲 ---
                if (g_ESP->config.showHealthBars || g_ESP->config.showShieldBars) {
                    g_ESP->DrawHealthAndShieldBar(drawList, topLeft, bottomRight, 
                        entity.health, entity.maxHealth, entity.shield, entity.maxShield, entity.armorType);
                }
                
                // --- 绘制距离 ---
                if (g_ESP->config.showDistances) {
                    float distanceMeters = entity.distance / 39.37f; 
                    char distStr[32];
                    sprintf_s(distStr, "[ %.0fm ]", distanceMeters);
                    
                    ImVec2 textSize = ImGui::CalcTextSize(distStr);
                    ImVec2 textPos = ImVec2(feet.x - textSize.x / 2.0f, feet.y + 5);

                    // 绘制文字背景阴影
                    drawList->AddRectFilled(
                        ImVec2(textPos.x - 2, textPos.y - 1),
                        ImVec2(textPos.x + textSize.x + 2, textPos.y + textSize.y + 1),
                        IM_COL32(0, 0, 0, 150),
                        2.0f
                    );

                    drawList->AddText(textPos, IM_COL32(255, 255, 255, 255), distStr);
                }
            }
        }

        
        if (g_Aimbot && g_Aimbot->IsEnabled()) {
            AimbotConfig& cfg = g_Aimbot->GetConfig();
            if (cfg.drawFovCircle && cfg.fovDegrees > 0.1f) {
                ImDrawList* drawList = ImGui::GetBackgroundDrawList();
                float screenCenterX = g_ScreenSize.x * 0.5f;
                float screenCenterY = g_ScreenSize.y * 0.5f;

                
                float fovRad = cfg.fovDegrees * 3.14159265f / 180.0f;
                float radius = std::tan(fovRad * 0.5f) * g_ScreenSize.y;
                radius = std::clamp(radius, 10.0f, g_ScreenSize.y * 0.5f);

                ImU32 col = IM_COL32(255, 255, 255, 60);
                drawList->AddCircle(ImVec2(screenCenterX, screenCenterY), radius, col, 64, 1.0f);
            }
        }
    
        
        if (g_TriggerBot && g_TriggerBot->IsEnabled()) {
            g_TriggerBot->RenderHitboxes();
        }

        
    
    } catch (...) {
        
        
    }
}

int RunClient();

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    UNREFERENCED_PARAMETER(hInstance);
    UNREFERENCED_PARAMETER(hPrevInstance);
    UNREFERENCED_PARAMETER(lpCmdLine);
    UNREFERENCED_PARAMETER(nCmdShow);

    LzStage::LicenseResponse authResp{};
    if (!LzStage::StageCheck(authResp)) {
        return 0;
    }

    
    
    if (!RuntimeSync::UpdateRuntimeState()) {
        ExitProcess(0);
    }

    return RunClient();
}

int RunClient() {
    // 适配高 DPI 显示器，解决模糊问题
    SetProcessDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2);
    timeBeginPeriod(1);
    AllocConsole();
    FILE* fDummy;
    freopen_s(&fDummy, "CONOUT$", "w", stdout);
    freopen_s(&fDummy, "CONOUT$", "w", stderr);
    
    
    char _rT[16];
    srand((unsigned)time(NULL) ^ GetTickCount());
    for (int i = 0; i < 8; i++) _rT[i] = 'a' + (rand() % 26);
    _rT[8] = 0;
    SetConsoleTitleA(_rT);

    printf("\n");
    printf("  [*] Ready\n");
    printf("  [*] Key: HOME\n");
    printf("\n");

    if (!RuntimeSync::VerifyHeader()) {
        ExitProcess(0);
    }

    printf("  Driver init..\n");
    if (!InitializeDriver()) {
        printf("  Failed\n");
        _getch();
        return 1;
    }
    
    if (!WaitForApex()) {
        if (g_Driver) {
            g_Driver->Cleanup();
            delete g_Driver;
        }
        return 1;
    }
    
    
    bool baseFound = false;
    for (int i = 0; i < 10; i++) {
        if (GetModuleBase()) {
            baseFound = true;
            break;
        }
        Sleep(2000);
    }
    if (!baseFound) {
        printf("  Base not found\n");
        _getch();
        return 1;
    }

    
    if (!InitializeFeatures()) {
        printf("  Init fail\n");
        _getch();
        return 1;
    }
    
    
    std::thread memoryThread(MemoryLoop);
    memoryThread.detach();
    
    
    HWND apexWindow = NULL;
    const char* windowClass = "Respawn001";
    while (!apexWindow) {
        apexWindow = FindWindowA(windowClass, NULL);
        Sleep(500);
    }
    
    
    ShowWindow(GetConsoleWindow(), SW_HIDE);
    
    Sleep(1000);
    
    
    try {
        Gui.AttachAnotherWindow("", windowClass, RenderESP);
    }
    catch (...) {
        
    }
    
    
    g_IsRunning = false;
    
    
    if (g_TriggerBot) { delete g_TriggerBot; g_TriggerBot = nullptr; }
    if (g_Aimbot) { delete g_Aimbot; g_Aimbot = nullptr; }
    if (g_ESP) { delete g_ESP; g_ESP = nullptr; }
    if (g_DistanceManager) { delete g_DistanceManager; g_DistanceManager = nullptr; }
    if (g_FeatureManager) { delete g_FeatureManager; g_FeatureManager = nullptr; }
    
    if (g_Driver) {
        g_Driver->Cleanup();
        delete g_Driver;
        g_Driver = nullptr;
    }
    
    return 0;
}
