#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <winsock2.h>
#include <windows.h>
#include <string>
#include <vector>
#include <array>
#include <chrono>
#include "input/human_curve.hpp"

class KMBoxNet {
private:
    SOCKET m_socket = INVALID_SOCKET;
    sockaddr_in m_deviceAddr{};
    uint32_t m_macAddress = 0;
    bool m_isConnected = false;
    bool m_emulationMode = false; // Chế độ giả lập khi chưa cắm thiết bị thật
    bool m_ignoreWindowFocus = false; // Phục vụ unit tests chạy headless không bị fail
    static inline bool s_globalIgnoreWindowFocus = false;

    // Focus Interlock & Hardware Safety (INV-FOCUS-INTERLOCK-HARDWARE-SAFETY)
    std::array<bool, 256> m_heldHidKeys{};
    uint8_t m_heldMouseButtons = 0; // bitmask: 1=Left, 2=Right, 4=Middle
    mutable bool m_lastGameFocused = false;
    int m_forcedFocus = -1; // -1: Win32 check, 0: forced unfocused, 1: forced focused

    // Action Gatekeeper (INV-INPUT-ACTION-RATE-LIMIT): Giới hạn tối đa 14 action events/s
    std::vector<uint64_t> m_actionHistory;
    uint32_t m_maxActionsPerSecond = 14;
    bool m_rateLimitEnabled = true;

public:
    KMBoxNet();
    ~KMBoxNet();

    // Kết nối tới thiết bị qua IP, Port và mã MAC
    bool Connect(const std::string& ip, int port, uint32_t mac);
    void Disconnect();

    // Bật chế độ giả lập nếu người dùng chưa kết nối phần cứng
    void EnableEmulationMode(bool enable);

    // Thiết lập bỏ qua kiểm tra focus cửa sổ (dành cho unit test headless)
    void SetIgnoreWindowFocus(bool ignore) {
        m_ignoreWindowFocus = ignore;
        s_globalIgnoreWindowFocus = ignore;
        m_forcedFocus = ignore ? 1 : -1;
    }
    bool IsIgnoreWindowFocus() const { return m_ignoreWindowFocus; }
    static bool IsAnyIgnoreWindowFocus() { return s_globalIgnoreWindowFocus; }

    // Ép trạng thái focus cửa sổ phục vụ Unit Test (-1: Win32, 0: unfocused, 1: focused)
    void SetForcedWindowFocus(int forcedFocus) {
        m_forcedFocus = forcedFocus;
        if (forcedFocus == 1) {
            m_ignoreWindowFocus = true;
        } else if (forcedFocus == 0) {
            m_ignoreWindowFocus = false;
        }
    }
    int GetForcedWindowFocus() const { return m_forcedFocus; }

    // Kiểm tra an toàn: Game POE2 có đang active ở tiền cảnh không
    bool IsGameWindowFocused() const;

    // Cưỡng chế nhả toàn bộ các phím di chuyển, kỹ năng và chuột (Focus Loss Emergency Release)
    void ReleaseAllKeys();

    // Kiểm tra trạng thái phím/chuột đang được giữ trong phần cứng KMBox
    bool IsHidKeyHeld(uint8_t hid) const { return (hid < 256) ? m_heldHidKeys[hid] : false; }
    bool IsVkKeyHeld(uint8_t vk) const;
    uint8_t GetHeldMouseButtons() const { return m_heldMouseButtons; }

    // Di chuyển chuột tương đối (Hardware Relative Movement)
    bool MoveMouse(short rx, short ry);

    // Di chuyển chuột mượt mô phỏng sinh học (Humanized Smooth Movement)
    bool MoveMouseSmooth(int targetX, int targetY, HumanCurveGenerator& curveGen, int steps = 15, int stepDelayMs = 1);

    // Nhấp chuột (button: 1=Left, 2=Right, 4=Middle)
    bool ClickMouse(int button, int dwellTimeMs = 75);

    // Nhấn và nhả chuột phi khóa (Mouse Down / Up - Non-blocking Actuator)
    bool MouseDown(int button);
    bool MouseUp(int button);

    // Nhấp chuột mô phỏng sinh học (Humanized Click with Dwell Time)
    bool ClickMouseHumanized(int button, HumanCurveGenerator& curveGen, float meanMs = 65.0f, float stdDevMs = 12.0f);

    // Cuộn con lăn chuột (Mouse Wheel) - delta > 0: Zoom In / Cuộn Lên; delta < 0: Zoom Out / Cuộn Xuống
    bool Wheel(int delta);

    // Bảng ánh xạ hai chiều giữa Windows Virtual-Key (VK) và USB HID Scan Code
    static uint8_t VkToUsbHid(uint8_t vk);
    static uint8_t UsbHidToVk(uint8_t hid);

    // Nhấn và thả phím bàn phím (Nhận USB HID code, tự động chuyển đổi sang VK khi ở emulation mode)
    bool KeyDown(uint8_t hidScanCode);
    bool KeyUp(uint8_t hidScanCode);
    bool KeyPress(uint8_t hidScanCode, int dwellTimeMs = 75);
    bool SendKey(uint8_t hidScanCode, int dwellTimeMs = 75);

    // Hỗ trợ truyền trực tiếp Virtual-Key (VK)
    bool KeyDownVk(uint8_t vkCode);
    bool KeyUpVk(uint8_t vkCode);
    bool KeyPressVk(uint8_t vkCode, int dwellTimeMs = 75);

    // Action Gatekeeper (INV-INPUT-ACTION-RATE-LIMIT)
    bool CanPerformAction(bool isEmergency = false);
    void RecordAction();
    void SetRateLimitEnabled(bool enabled) { m_rateLimitEnabled = enabled; }
    bool IsRateLimitEnabled() const { return m_rateLimitEnabled; }
    void SetMaxActionsPerSecond(uint32_t maxActions) { m_maxActionsPerSecond = maxActions; }
    uint32_t GetMaxActionsPerSecond() const { return m_maxActionsPerSecond; }
    size_t GetRecentActionCount() const;
    void ClearActionHistory() { m_actionHistory.clear(); }

    bool IsConnected() const { return m_isConnected || m_emulationMode; }
    bool IsEmulationMode() const { return m_emulationMode; }
};
