#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <cstdint>
#include <vector>
#include <string>
#include <algorithm>
#include <cmath>

#include "common/protocol.hpp"
#include "common/math2d.hpp"
#include "input/kmbox_net.hpp"
#include "input/human_curve.hpp"
#include "common/fixed_keys.hpp"

namespace navigation {

enum class MovementMode : uint8_t {
    WASD = 0,
    MOUSE = 1       // ExiledBot 2 Move-Only Key / Click-To-Move
};

struct MovementConfig {
    MovementMode mode = MovementMode::WASD;
    uint8_t moveOnlyVk = 0x54;         // Phím 'T' (Move Only chuẩn ExiledBot 2)
    uint32_t wasdMinDwellMs = 250;     // Dwell-time tối thiểu khi giữ hướng để chống jitter (INV-WASD-MIN-DWELL)
    uint32_t mousePulseIntervalMs = 120;// Nhịp gửi lệnh di chuyển Move-Only
    float mouseMaxScreenDist = 520.0f;  // Cự ly trỏ chuột tối đa quanh tâm nhân vật
    bool pulseEWithForward = false;     // Cờ nhấp phím E hỗ trợ lướt (mặc định false)
};

/**
 * @brief MovementController - Hạt nhân điều khiển di chuyển dùng chung duy nhất (SSoT).
 * 
 * Học hỏi từ ExiledBot 2 (v0.10.1):
 * 1. Hỗ trợ chế độ Move-Only Key: trỏ chuột theo hướng waypoint và giữ/nhấp phím Move-Only (T).
 * 2. Hỗ trợ chế độ WASD phi khóa (Non-Blocking): giữ phím liên tục qua các tick 120Hz mà KHÔNG
 *    gọi sleep_for(), loại bỏ triệt để hiện tượng bước 1 bước dừng 1 bước (stop-and-go stutter).
 * 3. Chuyển hướng êm ái, dwell-time chuẩn INV-WASD-MIN-DWELL để triệt tiêu rung lắc micro-jitter.
 */
class MovementController {
public:
    explicit MovementController(const MovementConfig& config = MovementConfig{});

    void SetConfig(const MovementConfig& config) { m_config = config; }
    const MovementConfig& Config() const { return m_config; }
    void SetMode(MovementMode mode) { m_config.mode = mode; }
    MovementMode Mode() const { return m_config.mode; }

    /**
     * @brief Điều khiển nhân vật di chuyển theo vector thế giới (dx, dy).
     * Hàm này chạy trong Hot Path 120Hz, 0ms blocking sleep.
     * @param dx Độ lệch X trong tọa độ thế giới
     * @param dy Độ lệch Y trong tọa độ thế giới
     * @param kmbox Giao tiếp phần cứng KMBox
     * @param nowMs Mốc thời gian hiện tại (ms)
     * @return true nếu lệnh di chuyển đã được áp dụng
     */
    bool SteerTowards(float dx, float dy, KMBoxNet& kmbox, uint64_t nowMs);

    /**
     * @brief Dừng toàn bộ di chuyển (nhả phím WASD hoặc ngừng gửi Move-Only).
     */
    void Stop(KMBoxNet& kmbox);

    /**
     * @brief Kiểm tra xem hiện có đang giữ phím di chuyển không.
     */
    bool IsMoving() const { return !m_heldVks.empty() || m_isMoveOnlyActive; }

    /**
     * @brief Kiểm tra xem Move-Only key có đang được kích hoạt hay không.
     */
    bool IsMoveOnlyActive() const { return m_isMoveOnlyActive; }

    /**
     * @brief Lấy danh sách mã phím VK đang được giữ (Zero-Heap WasdKeyArray).
     */
    const common::WasdKeyArray& GetHeldKeys() const { return m_heldVks; }
    const common::WasdKeyArray& HeldVks() const { return m_heldVks; }

private:
    bool SteerWasd(float dx, float dy, KMBoxNet& kmbox, uint64_t nowMs);
    bool SteerMoveOnly(float dx, float dy, KMBoxNet& kmbox, uint64_t nowMs);

    MovementConfig m_config;
    HumanCurveGenerator m_curveGen;

    // Trạng thái WASD phi khóa (Zero-Heap WasdKeyArray)
    common::WasdKeyArray m_heldVks;
    common::WasdVector m_currentWasd{};
    uint64_t m_lastDirectionChangeMs = 0;
    uint64_t m_lastPulseEMs = 0;

    // Trạng thái Move-Only Key (ExiledBot 2)
    bool m_isMoveOnlyActive = false;
    uint64_t m_lastMousePulseMs = 0;
};

} // namespace navigation
