#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <cstdint>
#include <vector>
#include <cmath>
#include <chrono>
#include "memory/terrain_reader.hpp"
#include "navigation/pathfinder.hpp"

namespace navigation {

/**
 * @brief Lớp quản trị NavMesh Bitset kết hợp RAM Game và Minimap Fog of War (Doc 69 §3.4)
 * 
 * Lưu trữ trạng thái địa hình và sương mù dưới dạng mảng 64-bit bitset (1 bit/cell).
 * Cho phép thực hiện các phép toán giao thoa vùng (Bitwise Intersection) O(1) theo từng khối 64 ô:
 * - Direct Walkability Bitset: Trích xuất trực tiếp từ RAM game POE2.
 * - Exploration Fog Bitset: Theo dõi vùng đã được nhân vật quét qua / FoV đã mở.
 * - Frontier Bitset: Giao thoa giữa (Walkable & !Explored & HasExploredNeighbor).
 * Tối ưu hóa A* / JPS trên bitset để tìm đường xuyên suốt bản đồ trong < 1.0ms.
 */
class NavMeshBitsetFusion {
public:
    NavMeshBitsetFusion() = default;

    // Khởi tạo lưới bitset từ dữ liệu địa hình gốc đọc từ RAM
    bool InitializeFromNativeTerrain(const memory::NativeTerrainData& terrain);

    // Cập nhật vị trí nhân vật để xả sương mù (Fog of War Reveal) trong bán kính FoV (mặc định 60-80 units)
    void RevealFogAroundWorldPos(float worldX, float worldY, float revealRadius = 75.0f);

    // Đánh dấu ô lưới cụ thể đã khám phá
    void SetExploredGrid(uint32_t gx, uint32_t gy, bool explored = true);

    // Kiểm tra ô có đi được (từ RAM) và có sương mù hay không
    bool IsWalkable(uint32_t gx, uint32_t gy) const;
    bool IsExplored(uint32_t gx, uint32_t gy) const;
    bool IsWalkableWorld(float wx, float wy) const;
    bool IsExploredWorld(float wx, float wy) const;

    // Trích xuất các ô mép biên thám hiểm (Frontier Cells) siêu tốc bằng bitwise scan
    std::vector<GridCoord> ExtractFrontierCells(uint32_t maxFrontiers = 256) const;

    // Tìm đường đi toàn bản đồ từ Start tới Goal bằng A* / JPS tối ưu bitset
    // Thời gian tính toán < 1.0 ms
    std::vector<Vec2> FindGlobalPath(
        const Vec2& startWorld,
        const Vec2& goalWorld,
        float* outComputeTimeMs = nullptr
    ) const;

    // Tìm điểm Frontier tối ưu nhất để tiếp tục dọn dẹp map (kết hợp Information Gain & Distance)
    bool FindBestFrontierTarget(
        const Vec2& playerWorld,
        Vec2& outTargetWorld,
        float* outScore = nullptr
    ) const;

    // Tỷ lệ hoàn thành khám phá bản đồ (Explored Walkable / Total Walkable)
    float ExplorationProgress() const;

    uint32_t Cols() const { return m_cols; }
    uint32_t Rows() const { return m_rows; }
    uint32_t TotalWalkableCells() const { return m_totalWalkableCells; }
    uint32_t ExploredWalkableCells() const { return m_exploredWalkableCells; }

    bool WorldToGrid(float wx, float wy, uint32_t& outGx, uint32_t& outGy) const;
    bool GridToWorld(uint32_t gx, uint32_t gy, float& outWx, float& outWy) const;

private:
    uint32_t m_cols = 0;
    uint32_t m_rows = 0;
    uint32_t m_wordsPerRow = 0;
    float m_gridToWorldScale = 10.875f;
    float m_worldOriginX = 0.0f;
    float m_worldOriginY = 0.0f;

    uint32_t m_totalWalkableCells = 0;
    uint32_t m_exploredWalkableCells = 0;

    // Bitset 64-bit: 1 bit = 1 cell
    // Bit = 1 nghĩa là True (Walkable hoặc Explored)
    std::vector<uint64_t> m_walkableBits;
    std::vector<uint64_t> m_exploredBits;

    inline size_t WordIndex(uint32_t gx, uint32_t gy) const {
        return static_cast<size_t>(gy) * m_wordsPerRow + (gx / 64);
    }

    inline uint64_t BitMask(uint32_t gx) const {
        return 1ULL << (gx % 64);
    }
};

} // namespace navigation
