#pragma once

#include <cstdint>
#include <string>
#include <vector>
#include <memory>
#include "common/protocol.hpp"
#include "memory/game_layout.hpp"
#include "brain/bot_brain.hpp"
#include "input/kmbox_net.hpp"
#include "input/human_curve.hpp"

// ==========================================================
// Area Event Memory & Handler (Doc 29 - Phase P1)
//
// Quản lý trí nhớ sự kiện khu vực (Essence, Shrine, Breach,
// Ritual, Strongbox, Delirium) và đề xuất hành động cho Arbiter.
// Khóa cứng bất biến:
// - INV-EVENT-01: Không được rời map khi còn event committed!
// - INV-SAFE-01: Không mở rương/strongbox khi có quái sống trong safe_range!
// ==========================================================

enum class AreaEventStatus : uint8_t {
    Candidate,   // Thấy entity type 5–11 trên radar
    Committed,   // Bot quyết định tiếp cận & xử lý event (INV-EVENT-01)
    Completed,   // Tương tác xong / entity mở hoặc tiêu diệt
    Failed       // Thất bại quá 3 lần hoặc timeout 120s
};

struct AreaEventRecord {
    uint32_t entityId = 0;
    uint16_t type = 0; // EntityType 5-11
    float x = 0.0f;
    float y = 0.0f;
    float z = 0.0f;
    AreaEventStatus status = AreaEventStatus::Candidate;
    uint64_t lastSeenMs = 0;
    uint64_t commitTimeMs = 0;
    uint32_t failCount = 0;
    char name[48] = {};
};

struct AreaEventConfig {
    float eventEngageRange = 120.0f;    // Tầm quét bắt đầu commit event (world units)
    float chestRange = 60.0f;           // Cự ly mở rương/strongbox (world units)
    float safeRange = 50.0f;            // INV-SAFE-01: Cự ly kiểm tra quái sống (world units)
    float interactRadius = 25.0f;       // Cự ly đủ gần để click tương tác
    uint32_t timeoutMs = 120000;        // 120s timeout chuyển sang Failed
    uint32_t maxFails = 3;              // Quá 3 lần fail chuyển sang Failed
    int screenWidth = 2560;
    int screenHeight = 1440;
};

class AreaEventManager {
public:
    explicit AreaEventManager(const AreaEventConfig& config = AreaEventConfig{});

    // Reset toàn bộ bộ nhớ event khi sang instance mới (areaSeed đổi)
    void OnAreaChanged(uint32_t newAreaSeed);

    // Cập nhật candidate events từ snapshot telemetry hiện tại
    void UpdateCandidates(const TelemetryPacket& packet, uint64_t nowMs);

    // Kiểm tra có event nào đang Committed không (INV-EVENT-01)
    bool HasCommittedEvent() const;

    // Lấy event đang committed (nếu có)
    AreaEventRecord* GetCommittedEvent();
    const AreaEventRecord* GetCommittedEvent() const;

    // Commit một event candidate
    bool CommitEvent(uint32_t entityId, uint64_t nowMs);

    // Đánh dấu event hoàn thành hoặc thất bại
    void MarkCompleted(uint32_t entityId);
    void MarkFailed(uint32_t entityId);

    // Thêm hoặc cập nhật trực tiếp một record (dành cho calibration / mock harness test)
    void AddOrUpdateEvent(const AreaEventRecord& record);

    // Lấy danh sách toàn bộ event trong khu vực
    const std::vector<AreaEventRecord>& GetEvents() const { return m_events; }
    uint32_t CurrentAreaSeed() const { return m_currentAreaSeed; }

    const AreaEventConfig& Config() const { return m_config; }
    void SetConfig(const AreaEventConfig& cfg) { m_config = cfg; }

private:
    AreaEventConfig m_config;
    uint32_t m_currentAreaSeed = 0;
    std::vector<AreaEventRecord> m_events;
};

// Handler đề xuất AREA_EVENT (6500) và OPEN_CHEST (5500) cho BotBrain
class AreaEventHandler : public IActionHandler {
public:
    explicit AreaEventHandler(AreaEventManager* mgr = nullptr, const AreaEventConfig& config = AreaEventConfig{});

    const char* Name() const override { return "AreaEventHandler"; }
    ActionProposal Propose(const TelemetryPacket& packet, uint64_t nowMs) override;
    bool Execute(const ActionProposal& chosen, const TelemetryPacket& packet, KMBoxNet& kmbox, uint64_t nowMs) override;

    void SetEventManager(AreaEventManager* mgr) { m_eventMgr = mgr; }
    AreaEventManager* EventManager() const { return m_eventMgr; }

    void SetConfig(const AreaEventConfig& cfg) { m_config = cfg; }
    const AreaEventConfig& Config() const { return m_config; }
    void ReleaseApproachKeys(KMBoxNet& kmbox);

private:
    AreaEventManager* m_eventMgr = nullptr;
    AreaEventConfig m_config;
    uint64_t m_lastInteractMs = 0;
    HumanCurveGenerator m_curveGen;
    std::vector<uint8_t> m_heldWasdHids;
};
