#include "solomon_stats.h"

#include <library/cpp/iterator/cartesian_product.h>

TSolomonStats::TSolomonStats()
    : StatsBuffer_(
        TInstant::Now(),
        Config_.Slices.size(),
        TDuration::Seconds(15), // interval
        TDuration::Seconds(180), // maxStatsAge
        TDuration::Seconds(120) // maxWriteAge
    )
{
}

void TSolomonStats::CountBeacon(const TBeacon& beacon, std::optional<NGeobase::NImpl::StrList> clientASNList) {
    if (!clientASNList)
        return;
    if (!Config_.WatchedHosts.contains(beacon.Url.GetHost()))
        return;
    if (!Config_.WatchedSchemes.contains(beacon.Url.GetSchemeInfo().Str))
        return;

    auto currentTime = TInstant::Now();
    auto beaconTime = currentTime - beacon.Age;

    TStringBuf asnSlice;
    for (const auto& asn : *clientASNList) {
        if (!Config_.WatchedASNs.contains(asn))
            continue;
        asnSlice = asn;
        break; // we do not count the same request twice for different ASNs
    }
    if (!asnSlice) {
        asnSlice = Config_.DefaultASN;
    }

    const auto& hostSubslicesConfig = Config_.WatchedHosts.at(beacon.Url.GetHost());
    TStringBuf hostSubslice;
    for (const auto& subsliceConfig : hostSubslicesConfig.Slices) {
        if (!subsliceConfig.IPs.contains(beacon.ServerIp))
            continue;
        hostSubslice = subsliceConfig.Name;
        break;
    }
    if (!hostSubslice) {
        hostSubslice = hostSubslicesConfig.DefaultSlice;
    }

    const TSolomonStatsSlice slice = {
        TString(hostSubslice),
        beacon.LegacyStatus,
        TString(asnSlice)
    };
    size_t idx = Config_.IdxBySlice.at(slice);
    StatsBuffer_.VisitWritableStats(
        currentTime,
        beaconTime,
        [&idx, &beacon](TStatsBuffer::TStats& stats) {
            stats.at(idx) += beacon.Weight;
        }
    );
}
