#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

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

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

// ==========================================================
// QuestNavigator - Tự Động Tìm Đường, Chuyển Cảnh & Làm Quest POE2
// (Waypoint Runner, Zone Transition & NPC Auto-Interact)
// ==========================================================

struct QuestNavConfig {
    bool enabled = false;               // Bật/tắt tự động chạy Quest Campaign
    bool autoPatrol = true;             // Mặc định BẬT tự động tuần tra dò map khi kích hoạt nhiệm vụ
    uint32_t patrolTurnIntervalMs = 2800; // Định kỳ xoay góc khám phá map
    MovementMode moveMode = MovementMode::MOUSE; // Mặc định: di chuyển bằng Chuột (Click-to-Move)
    float mouseClickDistance = 220.0f;  // Bán kính pixel click chuột quanh nhân vật
    float combatStopDistance = 380.0f;  // Cự ly dừng di chuyển tuần tra để xả skill (380 cho đánh xa, 220 cho cận chiến)
    bool isRanged = true;               // Chế độ nhân vật đánh xa (mặc định TRUE)
    float interactRadius = 15.0f;       // Cự ly đủ gần để click tương tác
    uint32_t stepIntervalMs = 120;      // Tần suất gửi phím di chuyển
    uint32_t fastMoveIntervalMs = 200;  // Nhịp click chuột nhanh khi đường thẳng thông thoáng (loại bỏ khựng giật)
    uint32_t normalMoveIntervalMs = 450;// Nhịp click chuẩn khi gần mục tiêu
    bool enableMobilitySkillTravel = true; // Cho phép dùng Dodge Roll / skill cơ động khi chạy đường trường
    uint32_t mobilityCooldownMs = 3000; // Cooldown lướt đường dài
    uint8_t interactVk = 0;             // Deprecated: Trong POE2 KBM tương tác bằng Click LMB, CẤM phím F (Skill 8)
    uint32_t expectedMaxHP = 0;         // Dự kiến maxHP để bypass nghẽn chuyển map
    std::string targetZone = "";        // Khu vực bản đồ mục tiêu cụ thể (tuỳ chọn CLI --target-zone)
    MapScenario scenario = MapScenario::BOSS_RUSH; // Kịch bản vận hành trong map (Mặc định: BOSS_RUSH)
    bool autoPortalAfterBoss = true;    // Tự động mở Town Portal sau khi hạ Boss
    uint32_t postBossLootWaitMs = 2500; // Thời gian chờ nhặt đồ quanh Boss (2.5 giây)
    bool ignoreTrashMobsInRush = true;  // Bỏ qua quái rác trắng/magic khi ở chế độ Boss Rush
    float rushPatrolStep = 240.0f;      // Sải bước di chuyển nhanh trong Boss Rush (240u)
    uint8_t portalVk = 0xBE;            // Phím '.' mở Town Portal (VK_OEM_PERIOD 0xBE)
    uint8_t portalHid = 0x37;           // USB HID Keyboard . and > (0x37)
    bool pulseEWithForward = false;     // Nhấp phím 'E' cùng lúc di chuyển tiến
    bool mapRevealerMode = false;       // Chế độ dành cho người chơi xóa sương mù / mở full mini map ngoại vi
    bool autoDetectRevealer = true;     // Tự động nhận diện sương mù đã bị xóa ngoại vi
};

struct QuestNavState {
    uint64_t lastStepMs = 0;
    uint32_t targetEntityId = 0;
    std::string targetName = "";
    float targetDistance = 0.0f;
    bool isInteracting = false;
    uint32_t questsProgressed = 0;
    uint32_t waypointsUnlocked = 0;
    uint32_t zoneTransitions = 0;
    float exploreAngle = 0.785f;        // Góc tuần tra khởi điểm (45 độ)
    uint64_t lastDirectionChangeMs = 0; // Thời điểm đổi hướng tuần tra gần nhất
    bool isPatrolling = false;          // Đang trong chế độ tuần tra dò đường
    float lastPlayerX = 0.0f;           // Theo dõi vị trí chống kẹt tường
    float lastPlayerY = 0.0f;
    uint64_t lastPosCheckMs = 0;
    uint32_t stuckCycles = 0;           // Số chu kỳ kẹt tường liên tiếp
    float mapEntryX = 0.0f;             // Tọa độ cổng vào map ban đầu
    float mapEntryY = 0.0f;
    bool mapEntryRecorded = false;
    float maxDistanceFromEntry = 0.0f;  // Khoảng cách kỷ lục đã tiến sâu vào map
    MapScenario activeScenario = MapScenario::BOSS_RUSH; // Kịch bản đang kích hoạt
    bool bossSpotted = false;           // Đã phát hiện Boss trên Radar
    bool bossSlain = false;             // Boss đã bị tiêu diệt
    uint64_t bossSlainTimestampMs = 0;  // Thời điểm Boss bị hạ
    bool portalSpawned = false;         // Đã mở Portal thoát map
    uint32_t mapCompletedCount = 0;     // Đếm số map đã hoàn thành
    uint64_t lastMobilitySkillMs = 0;   // Thời điểm lướt cơ động gần nhất

    // [DUAL-MODE NAVIGATION] Cơ chế tương thích Map Revealer / Smoother
    bool isMapRevealedExternally = false; // Trạng thái nhận diện Minimap đã bị xóa sương mù ngoại vi
    uint32_t consecutiveVisitedSteps = 0; // Đếm số bước liên tiếp rơi vào ô đã thăm
    bool isJunctionBacktracking = false; // Đang quay lui khỏi ngõ cụt về ngã ba
    float backtrackTargetX = 0.0f;
    float backtrackTargetY = 0.0f;

    // [INV-NAV-TERRAIN-COMMERCIAL] Phản xạ trượt tiếp tuyến men theo bờ vật cản (Delta XYZ ~ 0)
    float prevPosSampleX = 0.0f;
    float prevPosSampleY = 0.0f;
    uint64_t lastMicroCheckMs = 0;
    bool isTangentSliding = false;
    int8_t tangentHand = 0;             // +1: Left/CCW, -1: Right/CW
    uint32_t tangentSlideCount = 0;
};

#include "navigation/terrain_grid.hpp"
#include "navigation/pathfinder.hpp"
#include "brain/bot_brain.hpp"

class AreaEventManager;
class CharacterFSM;
namespace navigation { class MovementController; }

class QuestNavigator : public IActionHandler {
public:
    explicit QuestNavigator(const QuestNavConfig& config = QuestNavConfig{});

    void SetCharacterFSM(CharacterFSM* fsm) { m_fsm = fsm; }
    CharacterFSM* GetCharacterFSM() const { return m_fsm; }
    void SetMovementController(navigation::MovementController* moveCtrl) { m_moveCtrl = moveCtrl; }
    navigation::MovementController* GetMovementController() const { return m_moveCtrl; }

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

    void SetConfig(const QuestNavConfig& config) {
        m_config = config;
        m_state.activeScenario = config.scenario;
        if (config.expectedMaxHP > 0) m_expectedMaxHP = config.expectedMaxHP;
        if (!config.targetZone.empty() && m_state.targetName.empty()) {
            m_state.targetName = config.targetZone;
        }
    }
    const QuestNavConfig& Config() const { return m_config; }
    QuestNavState& State() { return m_state; }

    void SetMapScenario(MapScenario scenario, bool autoPortal = true) {
        m_config.scenario = scenario;
        m_config.autoPortalAfterBoss = autoPortal;
        m_state.activeScenario = scenario;
    }
    MapScenario GetMapScenario() const { return m_config.scenario; }
    bool IsBossSlain() const { return m_state.bossSlain; }
    void ResetMapState() {
        m_state.bossSpotted = false;
        m_state.bossSlain = false;
        m_state.bossSlainTimestampMs = 0;
        m_state.portalSpawned = false;
        m_state.mapEntryRecorded = false;
        m_state.maxDistanceFromEntry = 0.0f;
        m_state.isMapRevealedExternally = m_config.mapRevealerMode;
        m_state.consecutiveVisitedSteps = 0;
        m_state.isJunctionBacktracking = false;
        m_state.backtrackTargetX = 0.0f;
        m_state.backtrackTargetY = 0.0f;
        ResetHeatmap();
    }

    // Pha 1: Dual-Mode Navigation & Topological Frontier (Smoother-Proof)
    bool IsMapRevealedExternally() const { return m_state.isMapRevealedExternally; }
    void SetMapRevealedExternally(bool revealed) { m_state.isMapRevealedExternally = revealed; }
    bool DetectRevealedMapState(const TelemetryPacket& packet);
    bool FindTopologicalFrontier(float playerX, float playerY, float& outGoalX, float& outGoalY);

    void SetExpectedMaxHP(uint32_t hp) { m_expectedMaxHP = hp; }
    uint32_t ExpectedMaxHP() const { return m_expectedMaxHP; }

    void SetTerrainGrid(navigation::TerrainGrid* grid) { m_terrainGrid = grid; }
    void SetAreaEventManager(AreaEventManager* mgr) { m_areaEventMgr = mgr; }
    AreaEventManager* GetAreaEventManager() const { return m_areaEventMgr; }

    // Exploration Heatmap (Bản đồ nhiệt ghi nhận vùng đã khám phá)
    static constexpr int32_t kHeatmapDim = 128;
    static constexpr float kHeatmapCellSize = 32.0f; // Mỗi ô 32u (~4096x4096u bao quát toàn map)

    void RecordPosition(float worldX, float worldY);
    uint8_t GetVisitCount(float worldX, float worldY) const;
    void ResetHeatmap();
    uint32_t TotalTilesVisited() const { return m_totalTilesVisited; }

    // Tiêu chí hoàn tất map & Thống kê mép sương Frontier (Doc 69 §3.4)
    float GetExplorationCoverage() const;
    bool IsMapFullyExplored(float threshold = 0.90f) const;

    // Cập nhật tìm đường và di chuyển tới mục tiêu nhiệm vụ kế tiếp
    bool Update(const TelemetryPacket& packet, KMBoxNet& kmbox, uint64_t nowMs);

    // Kích hoạt tương tác khi tới gần (Click LMB vào thực thể thế giới, cấm phím F)
    void TriggerInteract(KMBoxNet& kmbox, uint64_t nowMs, const std::string& objectName,
                         float targetX = 0.0f, float targetY = 0.0f, float playerX = 0.0f, float playerY = 0.0f);

    // Kích hoạt mở Town Portal thoát về Hideout/Làng sau khi hạ Boss
    void TriggerTownPortalExit(KMBoxNet& kmbox, uint64_t nowMs);

    // Dừng di chuyển và nhả toàn bộ phím WASD đang giữ (INV-WASD-MIN-DWELL)
    void StopMovement(KMBoxNet& kmbox);
    const std::vector<uint8_t>& CurrentlyHeldKeys() const { return m_currentlyHeldKeys; }
    void SendDirectionForTest(float dx, float dy, KMBoxNet& kmbox, uint64_t nowMs) { SendDirection(dx, dy, kmbox, nowMs); }

private:
    void SendDirection(float dx, float dy, KMBoxNet& kmbox, uint64_t nowMs = 0);
    void NavigateTo(float startX, float startY, float goalX, float goalY, KMBoxNet& kmbox, uint64_t nowMs);

    std::vector<uint8_t> m_currentlyHeldKeys;
    uint64_t m_lastDirectionChangeMs = 0;

    QuestNavConfig m_config;
    QuestNavState m_state;
    navigation::TerrainGrid* m_terrainGrid = nullptr;
    AreaEventManager* m_areaEventMgr = nullptr;
    CharacterFSM* m_fsm = nullptr;
    navigation::MovementController* m_moveCtrl = nullptr;
    navigation::Pathfinder m_pathfinder;
    std::vector<navigation::Vec2> m_waypoints;
    size_t m_waypointIdx = 0;
    navigation::Vec2 m_currentGoal{0.0f, 0.0f};
    uint64_t m_lastPathPlanMs = 0;
    HumanCurveGenerator m_curveGen;
    uint32_t m_expectedMaxHP = 0;

    // Exploration Heatmap data
    std::vector<uint8_t> m_visitedHeatmap;
    float m_heatmapOriginX = 0.0f;
    float m_heatmapOriginY = 0.0f;
    bool m_heatmapInitialized = false;
    uint32_t m_totalTilesVisited = 0;
};
