#pragma once

#include <cstdint>
#include <string>
#include <vector>

#include "memory/aob_scanner.hpp"
#include "memory/imemory_reader.hpp"
#include "memory/offset_registry.hpp"
#include "memory/vitals_fingerprint.hpp"

// ==========================================================
// registry_live_label - Đối chuẩn OffsetRegistry trên RAM sống
// (TASK-RE-PIPELINE-2026 / live semantic labeling)
//
// Nguyên tắc:
//   - Tái sử dụng PointerChainResolver::ResolveInGameState / ResolvePlayer
//     (Single Source of Logic — không viết validator song song).
//   - Chỉ gán target khi ValidateInGameState (qua Resolve*) thành công.
//   - KHÔNG ghi địa chỉ heap vào TOML (INV-OFFSET-01). JSON report được
//     phép chứa heap tạm thời để đối chuẩn; Python labeler chỉ persist RVA.
// ==========================================================
namespace registry_live_label {

struct ProbeHit {
    std::string kind;          // static_root | aob_pattern | compiled_ingame_aob
    int index = 0;             // 1-based registry index (0 = compiled)
    uintptr_t rva = 0;
    uintptr_t heapPtr = 0;
    bool readable = false;
    bool validInGame = false;
    bool playerResolved = false;
    bool entityMapResolved = false;
    uint32_t entityMapCap = 0;
    uint32_t entityMapCount = 0;
    uint32_t playerMaxHp = 0;
    bool lifeMatched = false;
    int esOffset = -1;
    int wardOffset = -1;
    int manaOffset = -1;
    int spiritOffset = -1;
    uint32_t esMax = 0;
    uint32_t wardMax = 0;
    uint32_t manaMax = 0;
    uint32_t spiritCur = 0;
    uint32_t spiritMax = 0;
    std::string pattern;       // AOB text if kind is aob_*
    int ripOffset = 0;
    uintptr_t matchVa = 0;
    size_t esDwordHits = 0;
    size_t chunkReadsFail = 0;
    std::string lifeDescribe;
};

struct LabelAssignment {
    std::string target;        // InGameState | EntityMap (relative only)
    std::string kind;
    int index = 0;
    uintptr_t rva = 0;
    std::string evidence;
};

struct Report {
    std::string generatedAt;
    uint32_t pid = 0;
    std::string buildId;
    std::string buildMatch;
    uintptr_t moduleBase = 0;
    size_t moduleSize = 0;
    std::vector<ProbeHit> hits;
    std::vector<LabelAssignment> labels;
    uintptr_t entityMapOffset = 0;
    vitals_fingerprint::Expected expected{};
    uintptr_t lifeComponentFromPlayer = 0; // relative, 0 = unknown (không phải heap)
};

// Probe từng static_root / AOB registry (+ compiled InGameState AOB) trên reader.
// compiledRootsDisabled=true để không dùng kKnownStaticRoots build cũ.
bool Probe(IMemoryReader& reader,
           const OffsetRegistry& registry,
           const ModuleInfo& mod,
           bool simulated,
           Report& out,
           const vitals_fingerprint::Expected* expected = nullptr);

bool WriteJson(const Report& report, const std::string& path);

std::string FormatHex(uintptr_t value);

} // namespace registry_live_label
