#pragma once

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <windows.h>
#include <cstdint>
#include <string_view>
#include "common/protocol.hpp"
#include "common/zone_classifier.hpp"

// ==========================================================
// AutoPOE2 - CharacterFSM (Character State Machine)
// Quản lý trạng thái vòng đời nhân vật cấp cao (Closed Farming Loop 2026)
// 120Hz Hot Path - Zero Dynamic Allocation - High Determinism
// ==========================================================

enum class CharacterState : uint8_t {
    Uninitialized = 0,
    TownIdle = 1,                 // Trong làng (Act 1-3 towns, Caravan, Encampment), nghỉ/chờ lệnh
    HideoutIdle = 2,              // Trong Hideout, nghỉ/chờ lệnh (CẤM Explore/Unstuck di chuyển)
    HideoutStashing = 3,          // Cất đồ vào hòm đồ Stash
    HideoutVendoring = 4,         // Bán rác / đổi ngoại tệ với NPC (Ange, etc.)
    HideoutMapDeviceApproach = 5, // Tiếp cận Map Device trong Hideout (MapDeviceHandler điều khiển)
    HideoutMapDeviceOpen = 6,     // Mở Map Device UI, nạp Waystone/Tablet, click Activate
    HideoutPortalEnter = 7,       // Bước vào cánh cổng Map Portal
    InMapExploring = 8,           // Đang trong Map chiến đấu: tuần tra, dọn bãi quái, A* frontier
    InMapCombat = 9,              // Đang giao chiến với quái vật / boss
    InMapLooting = 10,            // Đang nhặt đồ / mở hòm trong Map
    InMapPortalExit = 11,         // Map hoàn tất, bước vào portal về Hideout
    DeadOrRespawning = 12,        // Nhân vật tử trận, đang chờ click hồi sinh Checkpoint
    LoadingTransition = 13        // Đang chờ nạp màn hình / chuyển đổi instance map
};

inline const char* CharacterStateToString(CharacterState state) {
    switch (state) {
        case CharacterState::Uninitialized: return "Uninitialized";
        case CharacterState::TownIdle: return "TownIdle";
        case CharacterState::HideoutIdle: return "HideoutIdle";
        case CharacterState::HideoutStashing: return "HideoutStashing";
        case CharacterState::HideoutVendoring: return "HideoutVendoring";
        case CharacterState::HideoutMapDeviceApproach: return "HideoutMapDeviceApproach";
        case CharacterState::HideoutMapDeviceOpen: return "HideoutMapDeviceOpen";
        case CharacterState::HideoutPortalEnter: return "HideoutPortalEnter";
        case CharacterState::InMapExploring: return "InMapExploring";
        case CharacterState::InMapCombat: return "InMapCombat";
        case CharacterState::InMapLooting: return "InMapLooting";
        case CharacterState::InMapPortalExit: return "InMapPortalExit";
        case CharacterState::DeadOrRespawning: return "DeadOrRespawning";
        case CharacterState::LoadingTransition: return "LoadingTransition";
        default: return "Unknown";
    }
}

class MapDeviceHandler;
class InventoryHandler;
class NpcInteractionHandler;

class CharacterFSM {
public:
    CharacterFSM() = default;

    void SetMapDeviceHandler(MapDeviceHandler* handler) { m_mapDeviceHandler = handler; }
    void SetInventoryHandler(InventoryHandler* handler) { m_invHandler = handler; }
    void SetNpcHandler(NpcInteractionHandler* handler) { m_npcHandler = handler; }

    // Bật/tắt chế độ tự hành Auto-Farm (F8 / Master Toggle)
    void SetAutonomousEnabled(bool enabled) { m_autonomousEnabled = enabled; }
    bool IsAutonomousEnabled() const { return m_autonomousEnabled; }

    // Truy vấn trạng thái
    CharacterState State() const { return m_state; }
    void ForceState(CharacterState state, uint64_t nowMs);

    // Kiểm tra các invariant điều kiện
    bool IsTownOrHideoutIdle() const {
        return m_state == CharacterState::TownIdle || m_state == CharacterState::HideoutIdle;
    }

    bool CanExplore() const {
        return m_state == CharacterState::InMapExploring ||
               m_state == CharacterState::InMapCombat ||
               m_state == CharacterState::InMapLooting;
    }

    bool WantsPortalExit() const {
        return m_state == CharacterState::InMapPortalExit;
    }

    bool PendingStashAfterMap() const { return m_pendingStashAfterMap; }

    // Cooldown thử lại Map Device sau khi thất bại hoặc hủy (3000ms)
    static constexpr uint64_t kMapDeviceRetryCooldownMs = 3000;
    static constexpr uint64_t kStashGateMs = 4000;
    static constexpr uint64_t kMapMaxDurationMs = 360000;   // 6 phút hard safety timeout
    static constexpr uint64_t kMapMinDurationMs = 90000;    // 90s tối thiểu trước khi xem xét map exit
    static constexpr uint64_t kMapLegitimateQuietMs = 30000;// 30s hoàn toàn không còn quái sau khi xong mục tiêu

    uint64_t LastMapDeviceFailMs() const { return m_lastMapDeviceFailMs; }

    // Trạng thái mục tiêu bản đồ chuẩn Pro Player
    void SetBossSlain(bool slain) { m_bossSlain = slain; }
    bool IsBossSlain() const { return m_bossSlain; }
    void SetHeatmapCoverage(float coveragePct) { m_heatmapCoverage = coveragePct; }
    float GetHeatmapCoverage() const { return m_heatmapCoverage; }
    void SetForceMapCompleted(bool completed) { m_forceMapCompleted = completed; }
    float GetDistanceTraversed() const { return m_distanceTraversed; }

    static constexpr float kMinTraverseUnits = 1200.0f; // 1200u tối thiểu tuần tra theo INV-MAP-LEGITIMATE-CLEAR-V2
    static constexpr float kMinCoverageRatio = 0.80f;   // 80% mở sương tối thiểu

    // Kiểm tra tiêu chuẩn hoàn tất map Pro Player
    bool CheckMapCompleted(const TelemetryPacket& packet, uint64_t nowMs) const;

    // Cập nhật FSM mỗi tick 120Hz (0 dynamic allocation, O(1))
    void Update(const TelemetryPacket& packet, uint64_t nowMs);

    // Kích hoạt thủ công chu trình Map Device từ Hideout
    bool TriggerMapDeviceRoutine(uint64_t nowMs);

    void Reset();

private:
    void TransitionTo(CharacterState newState, uint64_t nowMs);

    CharacterState m_state = CharacterState::Uninitialized;
    bool m_autonomousEnabled = false;

    MapDeviceHandler* m_mapDeviceHandler = nullptr;
    InventoryHandler* m_invHandler = nullptr;
    NpcInteractionHandler* m_npcHandler = nullptr;

    uint32_t m_lastAreaSeed = 0;
    uint64_t m_stateEnterMs = 0;
    uint64_t m_lastLogMs = 0;
    CharacterState m_lastLoggedState = CharacterState::Uninitialized;
    uint64_t m_lastMapDeviceFailMs = 0;
    bool m_pendingStashAfterMap = false;
    uint64_t m_hideoutEnterMs = 0;
    uint64_t m_mapEnterMs = 0;
    uint64_t m_mapQuietStartMs = 0;

    // Tiêu chí hoàn tất map chuẩn Pro Player (INV-MAP-LEGITIMATE-CLEAR-V2)
    bool m_bossSlain = false;
    float m_heatmapCoverage = 0.0f;
    bool m_forceMapCompleted = false;
    float m_distanceTraversed = 0.0f;
    float m_lastPosX = 0.0f;
    float m_lastPosY = 0.0f;
};
