#pragma once

#include <cstdint>
#include <cstddef>

#define SHARED_MEM_NAME "Local\\POE2_Auto_SharedMem_v1"
#define SHARED_MEM_MAGIC 0x504F45324155544FULL // "POE2AUTO"
#define SHARED_MEM_SIZE (4 * 1024 * 1024)      // 4 MB
#define PROTOCOL_VERSION 0x00050005             // v0.5.5
#define MAX_ENTITIES_PER_SNAPSHOT 256
#define TERRAIN_GRID_DIM 128

// ==========================================================
// Bố cục bộ nhớ (Memory Layout v1.1 - Seqlock + SPSC Ring)
//  0x000000 : Header 64 bytes (cache line)
//  0x001000 : Telemetry slot 0 (ping)
//  0x011000 : Telemetry slot 1 (pong)  -> double-buffer chống torn-read
//  0x300000 : Command ring buffer 16 slot x 64 bytes
// ==========================================================
#define HEADER_OFFSET            0x000000
#define TELEMETRY_SLOT0_OFFSET   0x001000
#define TELEMETRY_SLOT_STRIDE    0x010000   // 64 KB mỗi slot (đủ chứa TelemetryPacket ~39 KB)
#define TELEMETRY_SLOT_COUNT     2
#define COMMAND_QUEUE_OFFSET     0x300000
#define COMMAND_QUEUE_CAPACITY   16
#define COMMAND_SLOT_STRIDE      64         // 1 slot = 64-byte cache line

#pragma pack(push, 1)

// Header đồng bộ hoá liên tiến trình.
// Các trường con trỏ tuần tự được truy cập nguyên tử qua std::atomic_ref
// (kích thước/offset nhị phân không đổi so với kiểu thường).
struct SharedMemoryHeader {
    uint64_t magic;              // "POE2AUTO"
    uint32_t protocolVersion;     // v0.5.5
    uint32_t isRunning;           // 1: Đang chạy, 0: Yêu cầu ngắt khẩn cấp

    // Con trỏ tuần tự nguyên tử (Atomic Sequence Counters)
    uint64_t telemetrySequence;   // Seqlock: số lần publish snapshot; slot dữ liệu = (seq & 1)
    uint64_t commandSequence;     // Write-cursor của hàng đợi lệnh (Agent là producer duy nhất)
    uint64_t commandReadIndex;    // Read-cursor của hàng đợi lệnh (Core là consumer duy nhất)

    uint64_t lastCoreHeartbeat;   // Milliseconds timestamp từ C++ Core
    uint64_t lastAgentHeartbeat;  // Milliseconds timestamp từ Python Agent
    uint64_t reserved;            // Đệm đủ 64 bytes cho 1 cache line
};

// Trạng thái nhân vật người chơi
struct PlayerTelemetryData {
    uint64_t playerAddr; // RCA: Pass player address via telemetry for RAM snapshotting
    float posX, posY, posZ;
    float yaw, pitch;
    
    uint32_t currentHP, maxHP;
    uint32_t currentMana, maxMana;
    uint32_t currentES, maxES;
    uint32_t currentWard, maxWard;
    uint32_t currentSpirit, maxSpirit;
    
    uint32_t activeWeaponSet;     // 1 hoặc 2
    uint32_t movementFlags;       // Bit 0: Moving, Bit 1: Rolling, Bit 2: Idle
    uint64_t debuffMask;          // Bitmask cho Freeze, Shock, Bleed...
};

// Dữ liệu từng thực thể quanh người chơi
struct EntityTelemetryData {
    uint32_t id;
    uint16_t type;                // 1: Monster, 2: ItemDrop, 3: Portal, 4: NPC, 5: Chest, 6: Shrine, 7: Essence, 8: Breach, 9: Ritual, 10: Strongbox, 11: Delirium, 12: MinimapPoi
    uint16_t rarity;              // 0: White, 1: Magic, 2: Rare, 3: Unique
    
    float posX, posY, posZ;
    float distanceToPlayer;
    
    uint32_t currentHP, maxHP;
    uint16_t staggerProgress;     // 0 - 10000 (0% - 100% Stagger Poise)
    uint16_t currentAnimationId;
    
    uint32_t extraFlags;          // Bit 0: Boss, Bit 1: Targetable, Bit 2: Dead, Bit 3: Interactable, Bit 4: HiddenNotWalkable, Bit 5: MinimapDerived
    char name[48];
};

// Dữ liệu khu vực hiện tại - cập nhật từ LogSensor (Giai đoạn 2, nhiệm vụ 2.1)
struct AreaTelemetryData {
    uint64_t areaLoadTimestampMs;  // Thời điểm loading screen kết thúc (Unix ms)
    uint32_t areaLevel;            // Level khu vực
    uint32_t areaSeed;             // Seed địa hình ngẫu nhiên (NavMesh cache key)
    char areaCode[32];             // "G1_1", "MapWorldsBeach"...
    char areaName[48];             // "The Riverbank", "Hideout"...
};

// Gói dữ liệu Telemetry ghi từ Core sang Agent
struct TelemetryPacket {
    uint64_t snapshotId;
    uint64_t timestamp;
    
    PlayerTelemetryData player;
    
    uint32_t entityCount;
    EntityTelemetryData entities[MAX_ENTITIES_PER_SNAPSHOT];
    
    uint8_t terrainWalkability[TERRAIN_GRID_DIM * TERRAIN_GRID_DIM];

    AreaTelemetryData area;
};

// Chế độ di chuyển trong POE2: Chuột (Click to Move) hoặc Bàn phím (WASD)
enum class MovementMode : uint8_t {
    MOUSE = 0, // Click chuột trái để di chuyển (Click-to-Move - Mặc định)
    WASD  = 1  // Phím W/A/S/D
};

// Kịch bản chơi game trong Map Endgame POE2
enum class MapScenario : uint8_t {
    BOSS_RUSH = 0,         // Săn Boss nhanh mở điểm Atlas & qua map kế tiếp
    ATLAS_QUEST_RUSH = 1,  // Ưu tiên thực thể nhiệm vụ Atlas / Citadel / Event
    FAST_CLEAR = 2,        // Dọn nhanh quái Rare/Pack lớn trên đường chính
    FULL_CLEAR = 3         // Thám hiểm toàn bộ bản đồ
};

// Mã lệnh điều khiển vĩ mô từ Agent về Core
enum class MacroOpCode : uint32_t {
    IDLE = 0,
    NAVIGATE_TO_COORD = 1,
    ENGAGE_TARGET = 2,
    PICKUP_ITEM = 3,
    CAST_EMERGENCY_PORTAL = 4,
    EXECUTE_STASH_ROUTINE = 5,
    EXECUTE_VENDOR_ROUTINE = 6,
    EXECUTE_MAP_DEVICE_ROUTINE = 7,
    EXECUTE_NPC_INTERACT_ROUTINE = 8,
    SELECT_ATLAS_NODE = 9,
    VERIFY_MAP_DEVICE_UI = 10,
    FORCE_PORTAL_RETURN = 11,
    SET_COMBAT_PROFILE = 12,
    SET_MAP_SCENARIO = 95,
    TRIGGER_WORLD_MAP_TRAVEL = 96,
    TRIGGER_AUTO_LOGIN = 97,
    RECALIBRATE_XYZ = 98,
    PANIC_STOP = 99
};

// Aliases định danh Opcode tương thích IPC (Chu Kỳ 6 SSoT)
constexpr MacroOpCode OPCODE_FORCE_PORTAL_RETURN = MacroOpCode::FORCE_PORTAL_RETURN;
constexpr MacroOpCode OPCODE_SET_COMBAT_PROFILE  = MacroOpCode::SET_COMBAT_PROFILE;

// Hồ sơ chiến thuật giao chiến (Combat Profile)
enum class CombatProfile : uint8_t {
    MOB_CLEARING    = 0, // Dọn dẹp quái thường / Pack AoE Clear (Mặc định)
    BOSS_BURST      = 1, // Dồn sát thương Boss / Single-target Stagger Burst
    SURVIVAL_KITING = 2  // Phòng thủ né đòn / Kiting / ES Recovery
};

// Bitmask cho targetZ khi opCode == SELECT_ATLAS_NODE (Doc 56)
constexpr uint32_t ATLAS_FLAG_REQUIRE_HOVER_VERIFY   = 0x01;
constexpr uint32_t ATLAS_FLAG_SOCKET_PRECURSOR_TOWER = 0x02;
constexpr uint32_t ATLAS_FLAG_AUTO_PROCEED_TO_WAYSTONE = 0x04;

// Gói tin lệnh vĩ mô
struct CommandPacket {
    uint64_t commandId;
    MacroOpCode opCode;
    
    float targetX, targetY, targetZ;
    uint32_t targetEntityId;
    
    uint32_t priority;
    uint32_t timeoutMs;
};

#pragma pack(pop)

// ==========================================================
// Kiểm chứng bố cục nhị phân tại thời điểm biên dịch
// (Bảo đảm tương thích 1:1 với ctypes Python phía Agent)
// ==========================================================
static_assert(sizeof(SharedMemoryHeader) == 64, "Header phải đủ 64 bytes (1 cache line)");
static_assert(offsetof(SharedMemoryHeader, telemetrySequence) == 16, "Offset telemetrySequence = 16");
static_assert(offsetof(SharedMemoryHeader, commandSequence) == 24, "Offset commandSequence = 24");
static_assert(offsetof(SharedMemoryHeader, commandReadIndex) == 32, "Offset commandReadIndex = 32");
static_assert(offsetof(SharedMemoryHeader, lastCoreHeartbeat) == 40, "Offset lastCoreHeartbeat = 40");
static_assert(offsetof(SharedMemoryHeader, lastAgentHeartbeat) == 48, "Offset lastAgentHeartbeat = 48");
static_assert(offsetof(SharedMemoryHeader, reserved) == 56, "Offset reserved = 56");
static_assert(sizeof(PlayerTelemetryData) == 84, "Kích thước PlayerTelemetryData = 84 bytes");
static_assert(sizeof(EntityTelemetryData) == 88, "Kích thước EntityTelemetryData = 88 bytes");
static_assert(sizeof(AreaTelemetryData) == 96, "Kích thước AreaTelemetryData = 96 bytes");
static_assert(sizeof(CommandPacket) == 36, "Kích thước CommandPacket = 36 bytes");
static_assert(sizeof(TelemetryPacket) == 39112, "Kích thước TelemetryPacket = 39112 bytes (gồm AreaTelemetryData 96B)");
static_assert(sizeof(TelemetryPacket) < TELEMETRY_SLOT_STRIDE, "Slot 64KB phải đủ chứa 1 snapshot");
