#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <cstdint>
#include <cstddef>
#include <array>

#include "input/kmbox_net.hpp"

namespace input {

enum class ActuatorActionType : uint8_t {
    None = 0,
    KeyboardVk = 1,
    KeyboardHid = 2,
    MouseButton = 3
};

/**
 * @brief ScheduledInputEvent - Sự kiện input đã phát lệnh Down và đang chờ Up theo dwell-time.
 * Cấu trúc POD 16 bytes, căn lề 16 bytes, 0 allocation.
 */
struct alignas(16) ScheduledInputEvent {
    ActuatorActionType type = ActuatorActionType::None;
    uint8_t vkCode = 0;
    uint8_t hidCode = 0;
    int mouseButton = 0;
    uint64_t releaseTimestampMs = 0;
    bool active = false;
};

/**
 * @brief NonBlockingActuator - Bộ chấp hành input phi khóa theo nhịp tick 120Hz (Phase P7 SSoT).
 * 
 * Loại bỏ hoàn toàn std::this_thread::sleep_for(dwellTimeMs) trong Hot Path:
 * 1. Khi bấm phím/chuột: Gửi ngay gói tin KeyDown / MouseDown tới KMBox Net UDP (<0.005ms).
 * 2. Đăng ký hạn giải phóng (nowMs + dwellTimeMs) vào mảng tĩnh 16 slots.
 * 3. Đầu mỗi tick 120Hz, ProcessPendingReleases(nowMs) kiểm tra slot nào đến hạn và gửi KeyUp/MouseUp.
 * 
 * Đảm bảo độ trễ dispatch < 0.005ms (5 microseconds) và tần số 120Hz phẳng tuyệt đối.
 */
class NonBlockingActuator {
public:
    explicit NonBlockingActuator(KMBoxNet& kmbox);

    /**
     * @brief Xử lý giải phóng các phím đã hết hạn dwell-time.
     * Gọi đầu mỗi tick 120Hz (độ phức tạp O(1), thời gian chạy < 0.002ms).
     * @param nowMs Mốc thời gian hiện tại (ms)
     */
    void ProcessPendingReleases(uint64_t nowMs);

    /**
     * @brief Bấm phím Virtual-Key (VK) phi khóa.
     * Gửi ngay KeyDown, lên lịch KeyUp tại nowMs + dwellTimeMs (0ms sleep).
     */
    bool KeyPressVk(uint8_t vk, uint32_t dwellTimeMs, uint64_t nowMs);

    /**
     * @brief Bấm phím USB HID scan code phi khóa.
     */
    bool KeyPressHid(uint8_t hid, uint32_t dwellTimeMs, uint64_t nowMs);

    /**
     * @brief Click chuột phi khóa (1=Left, 2=Right, 4=Middle).
     */
    bool ClickMouse(int button, uint32_t dwellTimeMs, uint64_t nowMs);

    /**
     * @brief Giải phóng khẩn cấp toàn bộ các phím đang được giữ.
     */
    void ReleaseAll();

    /**
     * @brief Số lượng phím đang được giữ trong hàng đợi.
     */
    size_t ActiveSlotCount() const;

    /**
     * @brief Kiểm tra xem một phím VK cụ thể có đang trong trạng thái được giữ hay không.
     */
    bool IsKeyHeld(uint8_t vk) const;

    /**
     * @brief Đo đạc thời gian thực thi lệnh dispatch gần nhất (microseconds).
     */
    double GetLastDispatchTimeUs() const { return m_lastDispatchTimeUs; }

    KMBoxNet& GetKMBox() { return m_kmbox; }

private:
    void ReleaseSlot(const ScheduledInputEvent& slot);
    bool RegisterRelease(ActuatorActionType type, uint8_t vk, uint8_t hid, int btn, uint64_t releaseMs);

    KMBoxNet& m_kmbox;
    // Mảng tĩnh 16 slot cố định (khớp trọn vẹn 256 bytes = 4 Cache Lines)
    std::array<ScheduledInputEvent, 16> m_activeSlots{};
    double m_lastDispatchTimeUs = 0.0;
};

} // namespace input
