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

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

// -------------------------------------------------------------------------
// ClientScoreboardReader
// Reads the client-side player scoreboard from the network manager.
//
// Strategy
// --------
//  - Player identity strings (steamId, playerName) are cached by identity
//    pointer address: they are stable for the lifetime of a session.
//  - NetworkIds are re-read in a round-robin fashion because the engine
//    updates them after map-load.  Up to 16 IDs are refreshed per call;
//    the refresh interval is configurable (default 30 s).
//  - The final result is de-duplicated by NetworkId (or by playerName when
//    networkId == 0) and sorted by playerName.
// -------------------------------------------------------------------------

class ClientScoreboardReader {
public:
    explicit ClientScoreboardReader(int refreshIntervalMs = 30000);

    /// Populate @p players with the current scoreboard state.
    /// Returns false only when the fundamental scoreboard reads fail.
    bool TryRead(VmmAccessor&                       mem,
                 const RuntimeSession&              session,
                 std::vector<DayZScoreboardPlayer>& players);

    /// Clear all cached identity metadata.  Call on session restart.
    void Reset();

private:
    // Maximum number of identity slots in the scoreboard array
    static constexpr int kScoreboardCapacity = 120;
    static constexpr int kMaxPlayers         = 128;
    // How many stale NetworkIds to refresh per TryRead call
    static constexpr int kNetworkIdRefreshBatchSize = 16;

    struct IdentityMetadata {
        std::string                          steamId;
        std::string                          playerName;
        uint32_t                             networkId        = 0;
        std::chrono::steady_clock::time_point lastNetworkIdReadTime{};
    };

    std::unordered_map<uint64_t, IdentityMetadata> m_metadataByAddress;
    std::vector<DayZScoreboardPlayer>              m_cachedResult;
    int                                            m_networkIdRefreshCursor = 0;
    std::chrono::milliseconds                      m_networkIdRefreshInterval;

    /// Read or refresh the NetworkId for a single identity entry.
    void RefreshNetworkId(VmmAccessor& mem,
                          uint32_t     pid,
                          uint64_t     identityAddr,
                          IdentityMetadata& meta);
};
