#include <yandex/maps/wiki/social/rate_limiter_config_loader.h>
#include <maps/libs/common/include/exception.h>

namespace maps::wiki::social {

namespace {

const std::string LIMIT = "limits/limit";
const std::string INTERVAL = "interval";
const std::string VALUE = "value";

} // namespace

RateLimiterConfigLoader::RateLimiterConfigLoader(const maps::xml3::Node& node)
    : node_(node)
{}

RateLimiterConfigLoader::Limits RateLimiterConfigLoader::loadLimits(
    const std::string& section) const
{
    if (node_.isNull()) {
        return {};
    }

    auto node = node_.node(section, true);
    if (node.isNull()) {
        return {};
    }

    auto nodes = node.nodes(LIMIT, true);
    if (nodes.size() == 0) {
        return {};
    }

    Limits limits;

    for (size_t i = 0; i < nodes.size(); ++i) {
        auto limit = nodes[i];
        auto interval = limit.attr<size_t>(INTERVAL);
        auto value = limit.attr<size_t>(VALUE);

        limits.acceptableActivity.emplace(std::chrono::seconds(interval), value);
        limits.timeIntervals.push_back(std::chrono::seconds(interval));
    }

    return limits;
}

std::optional<std::chrono::seconds> findLimitExceeded(
    const RateLimiterConfigLoader::Limits& limits,
    const UserActivity& activity)
{
    for (const auto& [interval, limit] : limits.acceptableActivity) {
        auto it = activity.find(interval);
        ASSERT(it != activity.end());
        if (it->second >= limit) {
            return interval;
        }
    }
    return std::nullopt;
}

} // namespace maps::wiki::social
