#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <cstdint>
#include <cstddef>
#include <array>
#include <string>
#include <vector>

#include "memory/imemory_reader.hpp"
#include "memory/game_layout.hpp"

// ==========================================================
// PointerChainResolver - Bộ giải mã chuỗi con trỏ bộ nhớ POE2
// (Tier 1 Core Engine - Low-Level Pointer Chain Resolution)
//
// Thiết kế đáp ứng các tiêu chuẩn kỹ thuật:
//   1. Hỗ trợ cả backend giả lập (SimulatedMemoryReader) và game thật (RPM).
//   2. Tầng giải mã fallback 4 cấp độ:
//      - Cấp 1: Hot-path Cache O(1) (<0.001ms, 0 syscall, 0 heap alloc)
//      - Cấp 2: Static RVA cấu hình
//      - Cấp 3: Danh sách 8 static roots đã biết trong .data
//               (0x45CFEF8, 0x4715740, 0x45CCA20, 0x45D3280,
//                0x45D3288, 0x45CCA28, 0x45CCA30, 0x45D3290)
//      - Cấp 4: AOB Pattern Scanner (InGameStateBase)
//               "48 8B 05 ? ? ? ? 48 8B 40 38 48 8B 88 ? ? ? ? 48 85 C9 74"
//   3. Bounds check an toàn tuyệt đối (Canonical Virtual Address Range).
//   4. Cấu trúc ResolvedPlayerState chứa đầy đủ Life / Pos address và Vitals.
// ==========================================================

#pragma pack(push, 1)
struct ResolvedPlayerState {
    uintptr_t lifeAddr = 0;
    uintptr_t posAddr = 0;
    uint32_t curHP = 0;
    uint32_t maxHP = 0;
    uint32_t curMana = 0;
    uint32_t maxMana = 0;
    uint32_t curES = 0;
    uint32_t maxES = 0;
    uint32_t curSpirit = 0;
    uint32_t maxSpirit = 0;
    uint32_t curWard = 0;
    uint32_t maxWard = 0;
    float x = 0.0f;
    float y = 0.0f;
    float z = 0.0f;
};
#pragma pack(pop)

struct PointerChainConfig {
    uintptr_t staticRva = 0;
    uintptr_t mainBase = 0;
    size_t moduleSize = 0;
    uintptr_t entityMapOffset = 0;
    uintptr_t playerOffset = 0;
    uintptr_t statOffset = 0;
    uintptr_t posOffset = 0;
    bool isSimulated = false;
};

class PointerChainResolver {
public:
    // Danh sách 8 static roots trong .data của PathOfExile.exe
    // Build 6AA2213C (12/09/2026): 0x45CCFE0, 0x45CCFD8, 0x45D4100, 0x45D3DD8, 0x45D40F8, 0x4716880, 0x4435F90, 0x4435F98
    static constexpr std::array<uintptr_t, 8> kKnownStaticRoots = {
        0x45CCFE0, 0x45CCFD8, 0x45D4100, 0x45D3DD8,
        0x45D40F8, 0x4716880, 0x4435F90, 0x4435F98
    };

    // Pattern nhị phân AOB dò tìm InGameStateBase
    static constexpr const char* kInGameStatePattern =
        "48 8B 05 ? ? ? ? 48 8B 40 38 48 8B 88 ? ? ? ? 48 85 C9 74";

    // Canonical address bounds cho 64-bit Windows User-Mode
    static constexpr uintptr_t kMinValidAddress = 0x10000ULL;
    static constexpr uintptr_t kMaxValidAddress = 0x7FFFFFFFFFFFULL;

    explicit PointerChainResolver(IMemoryReader& reader, const PointerChainConfig& config = {});

    // Core resolution methods theo đặc tả
    bool ResolveInGameState(uintptr_t& outInGame);
    bool ResolvePlayer(uintptr_t inGame, ResolvedPlayerState& outPlayer);
    bool ResolveEntityMap(uintptr_t inGame, uintptr_t& outEntityMap, uint32_t& outCap, uint32_t& outCount);

    // Overloads tiện ích (tự động gọi ResolveInGameState nếu inGame chưa có)
    bool ResolvePlayer(ResolvedPlayerState& outPlayer);
    bool ResolveEntityMap(uintptr_t& outEntityMap, uint32_t& outCap, uint32_t& outCount);

    // Dò tìm InGameState qua AOB Scanning trên module chính
    bool FindInGameStateViaAob(uintptr_t& outInGame);

    // Configuration & State Getters/Setters
    void SetMainBase(uintptr_t base, size_t size = 0);
    uintptr_t MainBase() const { return m_mainBase; }
    size_t ModuleSize() const { return m_moduleSize; }

    void SetStaticRva(uintptr_t rva) { m_staticRva = rva; }
    uintptr_t StaticRva() const { return m_staticRva; }

    void SetEntityMapOffset(uintptr_t offset) { m_entityMapOffset = offset; }
    uintptr_t EntityMapOffset() const { return m_entityMapOffset; }

    void SetPlayerOffset(uintptr_t offset) { m_playerOffset = offset; }
    uintptr_t PlayerOffset() const { return m_playerOffset; }

    void SetStatOffset(uintptr_t offset) { m_statOffset = offset; }
    uintptr_t StatOffset() const { return m_statOffset; }

    void SetPosOffset(uintptr_t offset) { m_posOffset = offset; }
    uintptr_t PosOffset() const { return m_posOffset; }

    void SetInGameAddress(uintptr_t addr) { m_cachedInGame = addr; }
    uintptr_t InGameAddress() const { return m_cachedInGame; }

    void SetSimulated(bool sim) { m_isSimulated = sim; }
    bool IsSimulated() const { return m_isSimulated; }

    // --------------------------------------------------------
    // INV-BUILD-01 (Build-Keyed Offset Knowledge)
    // Khi gate được "arm" mà build fingerprint KHÔNG khớp, Tier 2
    // (8 static root RVA biên dịch sẵn) bị VÔ HIỆU, vì các RVA đó đã được
    // chứng minh là suy ra từ một build client KHÁC.
    // Bằng chứng thực địa 10/09/2026 (bin/Release/memprobe_report.txt):
    //   build cũ: .text VSize=0x2E840BE, .data VA=0x3A03000
    //   build mới: .text VSize=0x2E83B6E, .data VA=0x3A02000  (dịch -0x1000)
    // --------------------------------------------------------
    void SetBuildGate(bool armed, bool buildMatches) {
        m_buildGateArmed = armed;
        m_buildGateMatches = buildMatches;
    }
    bool BuildGateArmed() const { return m_buildGateArmed; }
    bool BuildGateMatches() const { return m_buildGateMatches; }
    bool CompiledStaticRootsAllowed() const {
        return !m_buildGateArmed || m_buildGateMatches;
    }

    // Danh sách static root do OffsetRegistry cung cấp (đã build-matched),
    // được ưu tiên TRƯỚC danh sách biên dịch sẵn.
    void SetRegistryStaticRoots(std::vector<uintptr_t> roots) {
        m_registryRoots = std::move(roots);
    }
    const std::vector<uintptr_t>& RegistryStaticRoots() const { return m_registryRoots; }

    uintptr_t ResolvedRva() const { return m_resolvedRva; }

    // Xóa cache khi đổi instance / nạp map mới
    void InvalidateCache();

    // Bounds checking nhanh
    static constexpr bool IsValidAddress(uintptr_t addr) {
        return addr >= kMinValidAddress && addr <= kMaxValidAddress;
    }

    // Single Source of Logic cho đối chuẩn live (MemProbe label-registry).
    bool ValidateInGameState(uintptr_t candRoot) const;

private:
    bool EnsureMainBase();

    IMemoryReader& m_reader;
    uintptr_t m_mainBase = 0;
    size_t m_moduleSize = 0;
    uintptr_t m_staticRva = 0;
    uintptr_t m_entityMapOffset = 0;
    uintptr_t m_playerOffset = 0;
    uintptr_t m_statOffset = 0;
    uintptr_t m_posOffset = 0;
    bool m_isSimulated = false;

    // Hot-path cache
    uintptr_t m_cachedInGame = 0;
    uintptr_t m_resolvedRva = 0;

    // INV-BUILD-01 state
    bool m_buildGateArmed = false;
    bool m_buildGateMatches = false;
    std::vector<uintptr_t> m_registryRoots;
};
