#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 - "Game ảo" chạy hoàn toàn trong tiến trình
// (Giai đoạn 1 - cho phép phát triển & test EntityManager mà
//  KHÔNG cần game thật, không đọc RAM thật, rủi ro = 0)
//
// Dựng 1 khối bộ nhớ 8MB bố cục y hệt game thật (game_layout),
// mô phỏng: entity di chuyển, HP dao động, stagger boss chạy.
// Đọc dữ liệu qua CHUỖI CON TRỎ chuẩn - code EntityManager
// viết 1 lần chạy trên cả game thật lẫn game ảo.
// ==========================================================
class SimulatedMemoryReader : public IMemoryReader {
public:
    SimulatedMemoryReader() = default;
    ~SimulatedMemoryReader() override;

    const char* BackendName() const override {
        return "SimulatedMemoryReader (Virtual Game)";
    }

    // Dựng khối bộ nhớ giả lập + toàn bộ cấu trúc InGameState
    bool Initialize(size_t customSize = 0);
    void EnsureSize(size_t minSize);

    // IMemoryReader
    bool Attach(uint32_t pid) override;   // chấp nhận mọi PID (khuyến nghị game_layout::kSimulatedPid)
    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;

    // Truy cập raw buffer (dùng cho unit test can thiệp trực tiếp)
    uint8_t* Raw() { return m_memory.empty() ? nullptr : m_memory.data(); }

    // ---- Điều khiển thế giới giả lập ----

    // Tiến mô phỏng 1 bước: entity di chuyển, HP dao động, stagger chạy
    void Tick(float dtSeconds);

    // Spawn 1 entity vào slot trống. Trả về slot index, UINT32_MAX nếu đầy.
    uint32_t SpawnEntity(const game_layout::EntityMemory& tmpl);

    // Truy cập trực tiếp để test can thiệp (viết đúng ngữ cảnh single-thread)
    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:
    // RNG nội bộ (LCG) - dùng Tick() tránh phụ thuộc <random>
    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; // vx,vy theo slot entity
};