#pragma once
#include <string>
#include <vector>
#include <optional>

// nlohmann/json is included here only for the ParseStringOrArray helper.
// All other TUs that include this header will also pull in the JSON library,
// which is acceptable since nlohmann/json is header-only and already a project
// dependency.
#include <nlohmann/json.hpp>

struct ItemFilterDefinition {
    std::string              key;
    std::string              description;
    std::optional<std::string> color;
    std::vector<std::string> modelNames;
    std::vector<std::string> configNames;
    std::vector<std::string> typeNames;
    std::vector<std::string> names;
};

// -------------------------------------------------------------------------
// ItemFilterCatalog
// Loads item-filter definitions from a JSON config file and classifies
// entities by matching their name/type/config/model strings against the
// patterns defined in each filter.
// -------------------------------------------------------------------------

class ItemFilterCatalog {
public:
    /// Key used when no filter matches.
    static constexpr const char* kFallbackKey = "isOtherLoot";

    /// Default constructor — resolves config path relative to the executable.
    ItemFilterCatalog();

    /// Explicit config path constructor.
    explicit ItemFilterCatalog(const std::string& configPath);

    // Non-copyable, movable
    ItemFilterCatalog(const ItemFilterCatalog&)            = delete;
    ItemFilterCatalog& operator=(const ItemFilterCatalog&) = delete;
    ItemFilterCatalog(ItemFilterCatalog&&)                 = default;
    ItemFilterCatalog& operator=(ItemFilterCatalog&&)      = default;

    /// Classify an entity against the loaded filters.
    /// Returns the key of the first matching filter, or kFallbackKey.
    std::string Classify(const std::string& entityName,
                         const std::string& typeName,
                         const std::string& configName,
                         const std::string& modelName) const;

    [[nodiscard]] const std::vector<ItemFilterDefinition>& GetFilters() const {
        return m_filters;
    }

private:
    std::vector<ItemFilterDefinition> m_filters;
    std::string                       m_configPath;

    void Load();

    /// Returns true if any pattern is a substring of (or equals) value
    /// after both are normalised to lowercase.
    static bool MatchesAny(const std::vector<std::string>& patterns,
                           const std::string& value);

    /// Parse a JSON field that may be either a string or an array of strings.
    /// Returns an empty vector when the key is absent.
    static std::vector<std::string> ParseStringOrArray(const nlohmann::json& j,
                                                        const std::string& key);

    /// Trim whitespace and convert to lowercase.
    static std::string Normalize(const std::string& value);

    /// Apply Normalize to every element of a vector.
    static std::vector<std::string> NormalizeAll(const std::vector<std::string>& values);

    /// Write a minimal default config to m_configPath.
    void WriteDefaultConfig() const;
};
