#pragma once
#include <vector>
#include <unordered_map>
#include <chrono>
#include <string>

#include "Core/Models.h"
#include "Core/RuntimeSession.h"
#include "Memory/VmmAccessor.h"
#include "Readers/EntityTypeCache.h"

// Forward declaration — full definition lives in ItemFilterCatalog.h
class ItemFilterCatalog;

// -------------------------------------------------------------------------
// ItemListReader
// Incremental reader for the world's item slow-table.
// Uses the same SlowTable wire format (0x18-byte slots, flag at +0x0,
// entity pointer at +0x8) as SlowEntityListReader.
// Only items whose entity name passes the ItemFilterCatalog are kept.
// -------------------------------------------------------------------------

class ItemListReader {
public:
    explicit ItemListReader(ItemFilterCatalog& catalog,
                            int batchSize    = 64,
                            int readBudgetMs = 10,
                            int staleAfterMs = 5000);

    /// Incrementally read items into @p items.
    /// Returns false only when the table pointer itself cannot be read.
    bool TryRead(VmmAccessor&                    mem,
                 const RuntimeSession&           session,
                 std::vector<DayZItemListEntry>& items);

    /// Reset all state. Call when the game session restarts.
    void Reset();

private:
    // ------------------------------------------------------------------
    // Per-item bookkeeping
    // ------------------------------------------------------------------
    struct CachedItem {
        DayZItemListEntry                      entry;
        int                                    lastSeenGeneration   = 0;
        std::chrono::steady_clock::time_point  lastSeenTime;
        std::chrono::steady_clock::time_point  lastSuccessfulRead;
        int                                    failedTypeReads      = 0;
        int                                    failedPositionReads  = 0;
    };

    // ------------------------------------------------------------------
    // Internal helpers
    // ------------------------------------------------------------------
    void ProcessItem(VmmAccessor&                          mem,
                     const RuntimeSession&                 session,
                     uint64_t                              itemAddr,
                     std::chrono::steady_clock::time_point now);

    void CompleteScan(std::chrono::steady_clock::time_point now);

    void PruneExpiredItems(std::chrono::steady_clock::time_point now);

    std::vector<DayZItemListEntry>& BuildResult();

    /// Choose the best display name for an item from its type strings.
    /// Priority: cleanName > configName > filename-from-modelName > typeName.
    static std::string GetBestItemName(const std::string& cleanName,
                                       const std::string& configName,
                                       const std::string& modelName,
                                       const std::string& typeName,
                                       uint64_t           itemAddress);

    // ------------------------------------------------------------------
    // State
    // ------------------------------------------------------------------
    ItemFilterCatalog&                         m_filterCatalog;

    std::unordered_map<uint64_t, CachedItem>   m_items;
    EntityTypeCache                            m_typeCache;
    std::vector<DayZItemListEntry>             m_cachedResult;
    std::vector<uint64_t>                      m_sortedAddresses;

    int  m_cursorOffset           = 0;
    int  m_validEntriesSeenInScan = 0;
    int  m_scanGeneration         = 1;
    bool m_hasCompletedScan       = false;
    bool m_sortDirty              = true;
    bool m_resultDirty            = true;

    int                         m_batchSize;
    std::chrono::milliseconds   m_readBudget;
    std::chrono::milliseconds   m_staleAfter;

    static constexpr int kMinTableChunkEntries = 256;
    static constexpr int kMaxItems             = 4096;
};
