#include "adapters/eft/items/catalog/ItemTemplateClassifier.h"

#include <algorithm>
#include <initializer_list>
#include <ranges>
#include <string_view>

#include "adapters/il2cpp/ManagedRuntime.h"
#include "foundation/text/StringUtils.h"

namespace
{
    [[nodiscard]] bool contains_any(
        const std::string& value,
        const std::initializer_list<std::string_view> needles)
    {
        return std::ranges::any_of(needles, [&](const std::string_view needle)
        {
            return value.find(needle) != std::string::npos;
        });
    }
}

namespace ta::adapters::eft::items
{
    ta::features::items::contracts::ItemCategory ItemTemplateClassifier::classify(
        const Il2CppClass* klass)
    {
        using ta::features::items::contracts::ItemCategory;
        const std::string type = ta::foundation::text::lower_copy(type_name(klass));
        if (contains_any(type, {"ammotemplate", "ammobox"})) return ItemCategory::Ammo;
        if (contains_any(type, {"throw", "grenade"})) return ItemCategory::Weapon;
        if (contains_any(type, {"weaponmod", "modtemplate", "magazinetemplate", "sight", "scope"})) return ItemCategory::WeaponMod;
        if (contains_any(type, {"weapontemplate", "knifetemplate", "launchertemplate"})) return ItemCategory::Weapon;
        if (contains_any(type, {"armortemplate", "armorvest", "armorplate", "helmet", "headwear",
                                "tacticalrig", "vesttemplate", "rigtemplate", "backpack"})) return ItemCategory::Equipment;
        if (contains_any(type, {"medical", "meditem", "medkit", "drug", "stimulator"})) return ItemCategory::Medical;
        if (contains_any(type, {"food", "drink"})) return ItemCategory::Diet;
        if (contains_any(type, {"keytemplate", "keycard"})) return ItemCategory::Key;
        if (contains_any(type, {"container", "caseitem", "stash"})) return ItemCategory::Container;
        if (contains_any(type, {"barter", "valuable", "buildingmaterial", "household", "electronic", "tooltemplate"})) return ItemCategory::TradeGoods;
        return ItemCategory::Other;
    }

    std::string ItemTemplateClassifier::type_name(const Il2CppClass* klass)
    {
        return ta::adapters::il2cpp::ManagedRuntime::class_chain_name(klass);
    }

    std::string ItemTemplateClassifier::search_text(
        const ta::features::items::contracts::ItemCatalogEntry& entry,
        const std::string& type)
    {
        std::string search;
        search.reserve(entry.id.size() + entry.name.size() + entry.short_name.size() + type.size() + 32);
        search.append(entry.id);
        search.push_back(' ');
        search.append(entry.name);
        if (!entry.short_name.empty())
        {
            search.push_back(' ');
            search.append(entry.short_name);
        }
        search.push_back(' ');
        search.append(ta::features::items::contracts::item_category_name(entry.category));
        if (!type.empty())
        {
            search.push_back(' ');
            search.append(type);
        }
        return ta::foundation::text::lower_copy(std::move(search));
    }
}
