#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"
#include "input/human_curve.hpp"
#include "brain/bot_brain.hpp"

namespace navigation {
class TerrainGrid;
}

// ==========================================================
// AutoPOE2 - MapDeviceHandler (Doc 29 - SPEC P5)
// Quản lý FSM Map Device & Vòng Lặp Farm Khép Kín (Closed Loop)
// ==========================================================

enum class MapDeviceState : uint8_t {
    Idle = 0,
    ApproachDevice = 1,        // Tiếp cận Map Device trong Hideout
    OpenDevice = 2,            // Click mở giao diện Map Device
    SelectAtlasNode = 3,       // [DOC-56] Click chọn Map Node tối ưu trên Atlas
    InspectPrecursorTowers = 4,// [DOC-56] Kiểm tra và nạp Precursor Tablet vào Tháp
    PlaceWaystone = 5,         // Lấy Waystone từ Inventory đặt vào slot Map Device
    PlaceTablet = 6,           // Đặt Precursor Tablet phụ trợ
    Activate = 7,              // Click nút Activate mở cổng Map
    WaitForPortals = 8,        // Chờ các cánh cổng portal mở ra
    EnterPortal = 9,           // Bước vào Portal (chuyển sang In-Map)
    Completed = 10,
    Failed = 11
};

inline const char* MapDeviceStateToString(MapDeviceState state) {
    switch (state) {
        case MapDeviceState::Idle: return "Idle";
        case MapDeviceState::ApproachDevice: return "ApproachDevice";
        case MapDeviceState::OpenDevice: return "OpenDevice";
        case MapDeviceState::SelectAtlasNode: return "SelectAtlasNode";
        case MapDeviceState::InspectPrecursorTowers: return "InspectPrecursorTowers";
        case MapDeviceState::PlaceWaystone: return "PlaceWaystone";
        case MapDeviceState::PlaceTablet: return "PlaceTablet";
        case MapDeviceState::Activate: return "Activate";
        case MapDeviceState::WaitForPortals: return "WaitForPortals";
        case MapDeviceState::EnterPortal: return "EnterPortal";
        case MapDeviceState::Completed: return "Completed";
        case MapDeviceState::Failed: return "Failed";
        default: return "Unknown";
    }
}

struct MapDeviceCoordinates {
    float refWidth = 1920.0f;
    float refHeight = 1080.0f;

    // Tọa độ Map Device UI (chuẩn 1080p)
    float waystoneSlotX = 420.0f;
    float waystoneSlotY = 480.0f;
    float tabletSlotX = 490.0f;
    float tabletSlotY = 480.0f;
    float activateButtonX = 806.0f;
    float activateButtonY = 563.0f;
    // TRAVERSE @2560x1440 = (1075, 750) -> 1080p (806, 563). Activate alias = TRAVERSE (POE2 không còn nút Activate kiểu POE1).
    float traverseButtonX = 806.0f;
    float traverseButtonY = 563.0f;
    float closeButtonX = 1860.0f;
    float closeButtonY = 60.0f;
    // Node Atlas xanh mặc định @2560x1440 (1410, 252) -> 1080p (1058, 189)
    float defaultAtlasNodeX = 1058.0f;
    float defaultAtlasNodeY = 189.0f;

    // Fallback tọa độ Map Device tại Shoreline Hideout (chuẩn 1080p: pixel (881, 484) -> 1440p (1175, 645))
    float shorelineFallbackX = 881.0f;
    float shorelineFallbackY = 484.0f;

    // Khóa chặn bất biến INV-MAPDEVICE-VERIFY-UI (mặc định false trong struct, toml hoặc explicit set sẽ bật true)
    bool requireUiVerification = false;
    uint32_t openDeviceTimeoutMs = 4500;
    uint32_t openDeviceRetryIntervalMs = 1800;

    // Atlas UI & Precursor Towers (Doc 56)
    float viewportCenterX = 960.0f;
    float viewportCenterY = 540.0f;
    float searchBoxX = 960.0f;
    float searchBoxY = 980.0f;
    float zoomInButtonX = 1820.0f;
    float zoomInButtonY = 480.0f;
    float zoomOutButtonX = 1820.0f;
    float zoomOutButtonY = 520.0f;
    uint32_t nodeHoverDelayMs = 120;
    float precursorTowerX = 960.0f;
    float precursorTowerY = 380.0f;
    uint32_t tabletInventoryRow = 1;

    // Inventory tham chiếu
    float invOriginX = 1272.0f;
    float invOriginY = 590.0f;
    float invCellW = 52.5f;
    float invCellH = 52.5f;
    int invCols = 12;
    int invRows = 5;

    // Cấu hình quét Waystone hàng đầu tiên (Row 0, 12 cột)
    uint32_t waystoneRow = 0;
    uint32_t waystoneColStart = 0;
    uint32_t waystoneColEnd = 11;
    bool autoScanFirstRow = true;
    uint32_t scanCellDelayMs = 40;

    // Delays
    uint32_t stepDelayMs = 350;
    uint32_t activateDelayMs = 2500;     // Chờ portal sau TRAVERSE (skill human-controls: 2.5s)
    uint32_t atlasLoadDelayMs = 1100;    // Chờ texture Atlas 1.0–1.2s trước khi click node
    uint32_t jitterMs = 50;
    float interactRadius = 18.0f; // Khoang cach tuong tac toi da Map Device (INV-NAV-TERRAIN-COMMERCIAL)

    struct Point {
        float x = 0.0f;
        float y = 0.0f;
    };

    Point ScalePoint(float rawX, float rawY, float screenW, float screenH) const {
        float sx = (screenW > 0.0f) ? (screenW / refWidth) : 1.0f;
        float sy = (screenH > 0.0f) ? (screenH / refHeight) : 1.0f;
        return { rawX * sx, rawY * sy };
    }
};

class MapDeviceHandler : public IActionHandler {
public:
    MapDeviceHandler();

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

    bool LoadCoordinates(const std::string& tomlPath);
    bool StartMapDevice(const CommandPacket& cmd, uint64_t nowMs);
    bool StartMapDevice(uint32_t waystoneCol, uint32_t waystoneRow, bool useTablet, uint64_t nowMs);
    void Reset();

    bool IsActive() const {
        return m_state != MapDeviceState::Idle &&
               m_state != MapDeviceState::Completed &&
               m_state != MapDeviceState::Failed;
    }

    MapDeviceState State() const { return m_state; }
    void ForceState(MapDeviceState state) { m_state = state; }
    float LastTargetScreenX() const { return m_lastTargetScreenX; }
    float LastTargetScreenY() const { return m_lastTargetScreenY; }
    const MapDeviceCoordinates& Coordinates() const { return m_coords; }
    void SetCoordinates(const MapDeviceCoordinates& coords) { m_coords = coords; }

    // Thống kê phiên chạy & cấu hình con trỏ Waystone
    uint32_t MapsOpenedCount() const { return m_mapsOpenedCount; }
    void SetWaystoneInventorySlot(uint32_t col, uint32_t row) {
        m_waystoneCol = col;
        m_waystoneRow = row;
    }
    uint32_t CurrentWaystoneCol() const { return m_currentWaystoneCol; }
    void SetCurrentWaystoneCol(uint32_t col) { m_currentWaystoneCol = col; }
    bool AutoScanFirstRow() const { return m_autoScanFirstRow; }
    void SetAutoScanFirstRow(bool enable) { m_autoScanFirstRow = enable; }

    // [DOC-56] Điều khiển & Định vị Atlas Node Selector
    bool SelectAtlasNode(const CommandPacket& cmd, uint64_t nowMs);
    bool SelectAtlasNode(float screenX, float screenY, uint32_t flags, uint32_t nodeId, uint64_t nowMs);
    void SetAtlasNodeTarget(float screenX, float screenY, uint32_t flags = 0x05, uint32_t nodeId = 0) {
        m_targetNodeX = screenX;
        m_targetNodeY = screenY;
        m_nodeFlags = flags;
        m_targetNodeId = nodeId;
        m_requiresNodeSelection = (screenX > 0.0f && screenY > 0.0f);
    }
    bool RequiresNodeSelection() const { return m_requiresNodeSelection; }
    float TargetNodeX() const { return m_targetNodeX; }
    float TargetNodeY() const { return m_targetNodeY; }
    uint32_t NodeFlags() const { return m_nodeFlags; }
    uint32_t TargetNodeId() const { return m_targetNodeId; }

    // [INV-NAV-TERRAIN-COMMERCIAL]
    bool IsZoomedIn() const { return m_isZoomedIn; }
    void SetZoomedIn(bool z) { m_isZoomedIn = z; }
    bool HasDeviceWorldPos() const { return m_hasDeviceWorldPos; }
    float DeviceWorldX() const { return m_deviceWorldX; }
    float DeviceWorldY() const { return m_deviceWorldY; }
    float DeviceWorldZ() const { return m_deviceWorldZ; }
    void SetDeviceWorldPos(float x, float y, float z) {
        m_deviceWorldX = x;
        m_deviceWorldY = y;
        m_deviceWorldZ = z;
        m_hasDeviceWorldPos = true;
    }

    void SetTerrainGrid(navigation::TerrainGrid* grid) { m_terrainGrid = grid; }
    navigation::TerrainGrid* GetTerrainGrid() const { return m_terrainGrid; }
    HumanCurveGenerator& CurveGenerator() { return m_curveGen; }
    void ReleaseApproachKeys(KMBoxNet& kmbox);
    bool InteractFSent() const { return m_interactFSent; }

    // [INV-MAPDEVICE-VERIFY-UI] Xác thực Atlas UI đã mở
    bool IsAtlasUiVerified() const { return m_atlasUiVerified; }
    void SetAtlasUiVerified(bool verified) { m_atlasUiVerified = verified; }

private:
    navigation::TerrainGrid* m_terrainGrid = nullptr;
    HumanCurveGenerator m_curveGen;
    float m_lastTargetScreenX = 0.0f;
    float m_lastTargetScreenY = 0.0f;

    bool AdvanceFsm(const TelemetryPacket& packet, KMBoxNet& kmbox, uint64_t nowMs);
    bool IsSafeTownZone(const TelemetryPacket& packet) const;
    void HoldApproachWasd(const std::vector<uint8_t>& hids, KMBoxNet& kmbox);

    MapDeviceCoordinates m_coords;
    MapDeviceState m_state = MapDeviceState::Idle;

    CommandPacket m_activeCmd{};
    uint64_t m_routineStartMs = 0;
    uint64_t m_lastStepMs = 0;

    uint32_t m_waystoneCol = 0;
    uint32_t m_waystoneRow = 0;
    uint32_t m_currentWaystoneCol = 0;
    bool m_autoScanFirstRow = true;
    bool m_useTablet = false;

    // [DOC-56] Atlas Node Target
    float m_targetNodeX = 0.0f;
    float m_targetNodeY = 0.0f;
    uint32_t m_nodeFlags = 0;
    uint32_t m_targetNodeId = 0;
    bool m_requiresNodeSelection = false;
    bool m_hoverStarted = false;

    uint32_t m_mapsOpenedCount = 0;
    uint32_t m_targetDeviceEntityId = 0;
    uint32_t m_targetPortalEntityId = 0;

    // [INV-NAV-TERRAIN-COMMERCIAL] Dynamic Camera Zoom-in & 3D World To Screen Tracking
    bool m_isZoomedIn = false;
    uint32_t m_zoomSteps = 4;
    float m_deviceWorldX = 0.0f;
    float m_deviceWorldY = 0.0f;
    float m_deviceWorldZ = 0.0f;
    bool m_hasDeviceWorldPos = false;
    int8_t m_tangentHand = 0;
    float m_lastPlayerX = 0.0f;
    float m_lastPlayerY = 0.0f;
    uint64_t m_lastMoveCheckMs = 0;
    std::vector<uint8_t> m_heldApproachHids;
    bool m_interactFSent = false;
    uint64_t m_atlasOpenedMs = 0;
    float m_portalWorldX = 0.0f;
    float m_portalWorldY = 0.0f;
    bool m_hasPortalWorldPos = false;
    bool m_panelsClosed = false;

    // [INV-MAPDEVICE-VERIFY-UI]
    bool m_atlasUiVerified = false;
    uint32_t m_openDeviceRetryCount = 0;
    uint64_t m_lastOpenClickMs = 0;
    uint64_t m_firstOpenClickMs = 0;
};

