#pragma once

#ifndef NOMINMAX
#define NOMINMAX
#endif
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <cstdint>
#include <vector>
#include <string>
#include <cmath>
#include <unordered_set>
#include "common/protocol.hpp"
#include "navigation/pathfinder.hpp"

namespace looting {

struct LootCluster {
    int clusterId = 0;
    navigation::Vec2 centerPos{ 0.0f, 0.0f };
    std::vector<uint32_t> entityIds;
    std::vector<uint32_t> packetIndices;
    
    float totalChaosValue = 0.0f;       // Tổng giá trị Chaos quy đổi tương đương
    int highestPriority = 0;            // Độ ưu tiên cao nhất
    bool hasCriticalItem = false;       // Priority >= 90 (Divine, Mirror, Tier 15+ Waystone)
    
    float distanceToPlayer = 0.0f;      // Khoảng cách tới người chơi
    bool isBacktracking = false;        // Đi ngược hướng tiến trình bản đồ (cos θ < 0)
    float detourAngleDeg = 0.0f;        // Góc lệch với hướng tiến trình (0..180 độ)
    float kineticCostSeconds = 0.0f;    // Thời gian tiêu tốn (di chuyển + dwell + penalty)
    float valueDensity = 0.0f;          // Chaos / Giây (VDS - Value Density Score)
    bool shouldPickup = false;          // Quyết định nhặt hay bỏ qua
};

struct LootClusterConfig {
    float clusterRadius = 25.0f;              // Bán kính gom cụm không gian (25 units)
    float playerMovementSpeed = 38.0f;        // Tốc độ di chuyển ước tính của nhân vật (units/sec)
    float itemPickupDwellSec = 0.05f;         // Thời gian nhặt mỗi món đồ (50ms)
    float minDensityThreshold = 0.35f;        // Ngưỡng mật độ tối thiểu (0.35 Chaos/giây)
    float backtrackPenaltyFactor = 2.5f;      // Hệ số phạt thời gian khi đi ngược hướng
    float minBacktrackChaosValue = 1.0f;      // Nếu đi ngược đường, tổng giá trị cụm phải >= 1.0 Chaos mới cho phép quay đầu
};

class LootDensityClusterer {
public:
    explicit LootDensityClusterer(const LootClusterConfig& config = LootClusterConfig{});

    void SetConfig(const LootClusterConfig& config) { m_config = config; }
    const LootClusterConfig& Config() const { return m_config; }

    // Ước tính giá trị quy đổi sang Chaos Orb dựa trên Taxonomy POE2
    static float EstimateItemValueInChaos(const EntityTelemetryData& item);

    // Gom cụm danh sách vật phẩm rơi trên mặt đất và đánh giá mật độ giá trị kinh tế
    std::vector<LootCluster> ClusterAndEvaluate(
        const TelemetryPacket& packet,
        const navigation::Vec2& playerPos,
        const navigation::Vec2& mapProgressionDir, // Hướng tiến trình của bản đồ (Frontier Vector)
        const std::unordered_set<uint32_t>& ignoredIds
    ) const;

    // Chọn cụm tốt nhất để nhặt trong tick hiện tại (trả về nullptr nếu không có cụm nào thỏa mãn)
    const LootCluster* SelectBestCluster(const std::vector<LootCluster>& clusters) const;

    // Sắp xếp thứ tự nhặt tối ưu bên trong 1 cụm theo Nearest-Neighbor (cục bộ TSP)
    std::vector<uint32_t> OrderItemsWithinCluster(
        const LootCluster& cluster,
        const TelemetryPacket& packet,
        const navigation::Vec2& playerPos
    ) const;

private:
    LootClusterConfig m_config;
};

} // namespace looting
