#pragma once

#include <cstdint>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <cmath>

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>

#include "brain/bot_brain.hpp"
#include "common/protocol.hpp"
#include "input/kmbox_net.hpp"

struct UnstuckConfig {
    uint32_t failMovementCheckIntervalMs = 10000; // 10s không đổi vị trí (Doc 29 mục 15)
    uint32_t maxRepetitiveMap = 1200;             // 1200 ticks (~10s ở 120Hz) cùng action & target entity trong map
    uint32_t maxRepetitiveTown = 360;             // 360 ticks (~3s ở 120Hz) cùng action ở town
    uint32_t maxPickupFails = 5;                  // 5 lần nhặt hỏng -> blacklist item ID
    uint32_t maxRecoveryAttempts = 3;             // Tối đa 3 lần thử gỡ kẹt trước khi emergency portal
    float minMovementDelta = 3.0f;                // Di chuyển ít hơn 3.0u bị coi là đứng yên
    float unstuckRadius = 50.0f;                  // Bán kính bước né kẹt (30-80 unit)
    uint8_t portalVk = 0xBE;                      // Phím '.' mở Town Portal (VK_OEM_PERIOD 0xBE)
    uint8_t portalHid = 0x37;                     // USB HID Keyboard . and > (0x37)
};

enum class UnstuckReason : uint8_t {
    None = 0,
    MovementStuck = 1,
    RepetitiveAction = 2,
    PickupFailure = 3
};

inline const char* UnstuckReasonToString(UnstuckReason r) {
    switch (r) {
        case UnstuckReason::MovementStuck: return "MovementStuck";
        case UnstuckReason::RepetitiveAction: return "RepetitiveAction";
        case UnstuckReason::PickupFailure: return "PickupFailure";
        default: return "None";
    }
}

class CharacterFSM;

class UnstuckHandler : public IActionHandler {
public:
    explicit UnstuckHandler(const UnstuckConfig& config = UnstuckConfig{});

    void SetCharacterFSM(CharacterFSM* fsm) { m_fsm = fsm; }
    CharacterFSM* GetCharacterFSM() const { return m_fsm; }
    void SetIsTown(bool isTown) { m_isTown = isTown; }
    bool IsTown() const { return m_isTown; }

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

    // Quan sát và theo dõi hành động của BotBrain
    void RecordAction(BotActionKind kind, uint32_t entityId, uint64_t nowMs, bool isTown = false);
    void RecordPickupFailure(uint32_t itemId);
    void RecordPickupSuccess(uint32_t itemId);
    bool IsItemBlacklisted(uint32_t itemId) const;
    void ClearBlacklist() { m_blacklistedItemIds.clear(); m_pickupFailCounts.clear(); }

    // Trạng thái gỡ kẹt
    bool IsStuck() const { return m_reason != UnstuckReason::None; }
    UnstuckReason Reason() const { return m_reason; }
    uint32_t RecoveryAttempts() const { return m_recoveryAttempts; }
    void ManualTriggerStuck(UnstuckReason reason, uint64_t nowMs);
    void Reset();
    void ReleaseHeldWasd(KMBoxNet& kmbox);

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

private:
    UnstuckConfig m_config;

    // Theo dõi vị trí nhân vật (Movement Check)
    float m_lastCheckX = 0.0f;
    float m_lastCheckY = 0.0f;
    float m_lastCheckZ = 0.0f;
    uint64_t m_lastMovementCheckMs = 0;
    bool m_initialPosRecorded = false;

    // Tọa độ lúc bắt đầu kẹt
    float m_stuckOriginX = 0.0f;
    float m_stuckOriginY = 0.0f;
    bool m_stuckOriginRecorded = false;

    // Theo dõi hành động lặp (Repetitive Action Check)
    BotActionKind m_lastActionKind = BotActionKind::None;
    uint32_t m_lastActionEntityId = 0;
    uint32_t m_consecutiveActionCount = 0;

    // Blacklist vật phẩm không thể nhặt
    std::unordered_map<uint32_t, uint32_t> m_pickupFailCounts;
    std::unordered_set<uint32_t> m_blacklistedItemIds;

    // Tiến trình gỡ kẹt
    UnstuckReason m_reason = UnstuckReason::None;
    uint32_t m_recoveryAttempts = 0;
    uint64_t m_lastRecoveryMs = 0;
    uint32_t m_escapeStep = 0;
    std::vector<uint8_t> m_heldWasdHids;
    uint64_t m_wasdHoldUntilMs = 0;

    CharacterFSM* m_fsm = nullptr;
    bool m_isTown = false;
};
