#pragma once
// ── CS2 External C++ WebRadar — Offset System ────────────────────────────────
// Dual mode: load from JSON files at runtime (matching C# Offsets.cs), with
// constexpr compile-time fallback values from cs2-dumper.
// JSON files expected: output/offsets.json, output/client_dll.json, output/buttons.json

#include <cstdint>
#include <string>
#include <unordered_map>
#include <nlohmann/json.hpp>

// ── Runtime offset container (loaded from JSON) ─────────────────────────────

struct Offsets {
    // ── Module-level offsets (from offsets.json) ────────────────────────────
    // client.dll
    static std::ptrdiff_t dwLocalPlayerPawn;
    static std::ptrdiff_t dwLocalPlayerController;
    static std::ptrdiff_t dwEntityList;
    static std::ptrdiff_t dwViewMatrix;
    static std::ptrdiff_t dwViewAngles;
    static std::ptrdiff_t dwPlantedC4;
    static std::ptrdiff_t dwGlobalVars;
    static std::ptrdiff_t dwGameRules;
    static std::ptrdiff_t dwGameEntitySystem;
    static std::ptrdiff_t dwGameEntitySystem_highestEntityIndex;
    static std::ptrdiff_t dwWeaponC4;
    static std::ptrdiff_t dwForceAttack;
    static std::ptrdiff_t dwForceJump;

    // engine2.dll
    static std::ptrdiff_t dwBuildNumber;
    static std::ptrdiff_t dwNetworkGameClient;

    // matchmaking.dll
    static std::ptrdiff_t dwGameTypes;

    // ── Entity fields (from client_dll.json classes) ────────────────────────
    static std::ptrdiff_t m_pGameSceneNode;      // C_BaseEntity
    static std::ptrdiff_t m_lifeState;            // C_BaseEntity
    static std::ptrdiff_t m_iHealth;              // C_BaseEntity
    static std::ptrdiff_t m_iTeamNum;             // C_BaseEntity
    static std::ptrdiff_t m_vOldOrigin;           // C_BasePlayerPawn
    static std::ptrdiff_t m_vecViewOffset;        // C_BaseModelEntity
    static std::ptrdiff_t m_vecAbsVelocity;       // C_BaseEntity
    static std::ptrdiff_t m_fFlags;               // C_BaseEntity
    static std::ptrdiff_t m_bDormant;             // CGameSceneNode
    static std::ptrdiff_t m_hOwnerEntity;         // C_BaseEntity

    static std::ptrdiff_t m_hPawn;                // CBasePlayerController
    static std::ptrdiff_t m_iszPlayerName;        // CBasePlayerController

    // CCSPlayerController
    static std::ptrdiff_t m_iPing;
    static std::ptrdiff_t m_iMVPs;
    static std::ptrdiff_t m_pActionTrackingServices;
    static std::ptrdiff_t m_pInGameMoneyServices;
    static std::ptrdiff_t m_pInventoryServices;

    // ActionTrackingServices
    static std::ptrdiff_t m_matchStats;

    // CSPerRoundStats_t (sub-struct offsets)
    static std::ptrdiff_t m_iKills;
    static std::ptrdiff_t m_iDeaths;
    static std::ptrdiff_t m_iAssists;
    static std::ptrdiff_t m_iScore;

    // InGameMoneyServices
    static std::ptrdiff_t m_iAccount;

    // C_CSPlayerPawn
    static std::ptrdiff_t m_AimPunchAngle;
    static std::ptrdiff_t m_pAimPunchServices;
    static std::ptrdiff_t m_iShotsFired;
    static std::ptrdiff_t m_iIDEntIndex;
    static std::ptrdiff_t m_bIsScoped;
    static std::ptrdiff_t m_bIsWalking;
    static std::ptrdiff_t m_flDetectedByEnemySensorTime;
    static std::ptrdiff_t m_entitySpottedState;
    static std::ptrdiff_t m_ArmorValue;

    // CCSPlayer_AimPunchServices
    static std::ptrdiff_t m_AimPunchCached;

    // C_CSPlayerPawnBase
    static std::ptrdiff_t m_flFlashDuration;
    static std::ptrdiff_t m_flFlashMaxAlpha;
    static std::ptrdiff_t m_angEyeAngles;

    // C_BasePlayerPawn
    static std::ptrdiff_t m_pWeaponServices;
    static std::ptrdiff_t m_pItemServices;
    static std::ptrdiff_t m_pObserverServices;

    // CPlayer_WeaponServices
    static std::ptrdiff_t m_hActiveWeapon;
    static std::ptrdiff_t m_hMyWeapons;            // CUtlVector<CHandle>

    // C_BasePlayerWeapon
    static std::ptrdiff_t m_iClip1;
    static std::ptrdiff_t m_pReserveAmmo;

    // CBasePlayerWeaponVData
    static std::ptrdiff_t m_iMaxClip1;

    // CCSPlayer_ItemServices
    static std::ptrdiff_t m_bHasHelmet;
    static std::ptrdiff_t m_bHasDefuser;

    // C_CSWeaponBase
    static std::ptrdiff_t m_bInReload;

    // C_PlantedC4
    static std::ptrdiff_t m_nBombSite;
    static std::ptrdiff_t m_bBombDefused;
    static std::ptrdiff_t m_flC4Blow;
    static std::ptrdiff_t m_flDefuseCountDown;
    static std::ptrdiff_t m_flDefuseLength;
    static std::ptrdiff_t m_bBeingDefused;

    // C_CSGameRules
    static std::ptrdiff_t m_bBombPlanted;
    static std::ptrdiff_t m_timeUntilNextPhaseStarts;
    static std::ptrdiff_t m_totalRoundsPlayed;
    static std::ptrdiff_t m_gamePhase;
    static std::ptrdiff_t m_iRoundTime;

    // CPlayer_ObserverServices
    static std::ptrdiff_t m_hObserverTarget;

    // C_EconEntity / C_EconItemView / C_AttributeContainer
    static std::ptrdiff_t m_Item;
    static std::ptrdiff_t m_pClippingWeapon;
    static std::ptrdiff_t m_AttributeManager;
    static std::ptrdiff_t m_iItemDefinitionIndex;

    // CSkeletonInstance
    static std::ptrdiff_t m_modelState;

    // CEntityInstance / CEntityIdentity (for dropped weapons)
    static std::ptrdiff_t m_pEntity;
    static std::ptrdiff_t m_designerName;

    // C_Team
    static constexpr std::ptrdiff_t m_iTeamScore   = 0x630;
    static constexpr std::ptrdiff_t m_szTeamname   = 0x634;

    // C_CSPlayerController
    static constexpr std::ptrdiff_t m_nPawnCharacterDefIndex = 0x912;

    // CGlobalVarsBase
    static constexpr std::ptrdiff_t m_mapName = 0x188;

    // C_C4
    static constexpr std::ptrdiff_t m_bBombPlanting = 0x1CB8;

    // C_SmokeGrenadeProjectile
    static constexpr std::ptrdiff_t smoke_m_nSmokeEffectTickBegin = 4688;
    static constexpr std::ptrdiff_t smoke_m_vSmokeDetonationPos   = 4712;

    // C_Inferno
    static constexpr std::ptrdiff_t inferno_m_firePositions        = 4120;
    static constexpr std::ptrdiff_t inferno_m_fireCount           = 6488;
    static constexpr std::ptrdiff_t inferno_m_nFireEffectTickBegin = 6508;
    static constexpr std::ptrdiff_t inferno_m_bFireIsBurning      = 5656;

    // GlobalVars / engine
    static constexpr std::ptrdiff_t m_nCurrentTickThisFrame = 0x34;

    // ── Bone index constants ────────────────────────────────────────────────
    static constexpr int BONE_PELVIS    = 1;
    static constexpr int BONE_SPINE0    = 2;
    static constexpr int BONE_SPINE1    = 3;
    static constexpr int BONE_SPINE2    = 4;
    static constexpr int BONE_NECK      = 6;
    static constexpr int BONE_HEAD      = 7;
    static constexpr int BONE_ARM_UPPER_L  = 9;
    static constexpr int BONE_ARM_LOWER_L  = 10;
    static constexpr int BONE_HAND_L       = 11;
    static constexpr int BONE_ARM_UPPER_R  = 13;
    static constexpr int BONE_ARM_LOWER_R  = 14;
    static constexpr int BONE_HAND_R       = 15;
    static constexpr int BONE_LEG_UPPER_L  = 17;
    static constexpr int BONE_LEG_LOWER_L  = 18;
    static constexpr int BONE_ANKLE_L      = 19;
    static constexpr int BONE_LEG_UPPER_R  = 20;
    static constexpr int BONE_LEG_LOWER_R  = 21;
    static constexpr int BONE_ANKLE_R      = 22;
    static constexpr int BONE_CHEST        = 23;

    // ── Bone array stride (each bone = 32 bytes, quat + pos) ────────────────
    static constexpr int BONE_STRIDE = 32;

    // ── Load offsets from JSON files ────────────────────────────────────────
    // Returns true on success, false if files not found (uses defaults).
    static bool load_all(const std::string& base_dir);

    // ── Validate critical offsets ───────────────────────────────────────────
    // Returns true if all critical offsets are non-zero.
    static bool validate();

private:
    static void load_offsets_json(const nlohmann::json& j);
    static void load_client_dll_json(const nlohmann::json& j);
    static void load_buttons_json(const nlohmann::json& j);
};
