#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <cstdint>
#include <vector>

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

// ==========================================================
// SimulatedMemoryReader - Giả lập bộ nhớ game POE2 cho Unit Test
// ==========================================================
class SimulatedMemoryReader : public IMemoryReader {
public:
    SimulatedMemoryReader() = default;
    ~SimulatedMemoryReader() override;

    const char* BackendName() const override {
        return "SimulatedMemoryReader (Virtual Game)";
    }

    bool Initialize(size_t customSize = 0);
    void EnsureSize(size_t minSize);

    bool Attach(uint32_t pid) override;
    void Detach() override;
    bool Read(uintptr_t address, void* buffer, size_t size) override;
    bool Write(uintptr_t address, const void* buffer, size_t size) override;
    bool ForEachReadableRegion(const RegionFn& fn) override;
    bool ForEachHeapRegion(const RegionFn& fn) override;

    uint8_t* Raw() { return m_memory.empty() ? nullptr : m_memory.data(); }

    void Tick(float dtSeconds);
    uint32_t SpawnEntity(const game_layout::EntityMemory& tmpl);

    game_layout::InGameStateMemory* InGame();
    game_layout::PlayerStateMemory* Player();
    game_layout::EntityMapMemory* EntityMap();
    game_layout::CameraMemory* Camera();
    game_layout::FogMemory* Fog();

    uintptr_t BaseAddress() const { return m_base; }
    uintptr_t CameraAddress() const { return m_base + game_layout::kCameraOffset; }
    uintptr_t FogAddress() const { return m_base + game_layout::kFogOffset; }
    bool IsInitialized() const { return !m_memory.empty(); }

    void SetAutoSimulate(bool enable) { m_autoSimulate = enable; }
    bool AutoSimulate() const { return m_autoSimulate; }

private:
    uint32_t NextRandom();

    std::vector<uint8_t> m_memory;
    uintptr_t m_base = game_layout::kSimulatedBaseAddress;
    uint32_t m_rngState = 0x12345678;
    bool m_autoSimulate = true;
    std::vector<float> m_velocities;
};
