#pragma once

#include <balancer/kernel/balancing/pessimization.h>

#define UNIT_ASSERT_EQUAL_EPS(a, b) \
    UNIT_ASSERT(std::abs((a) - (b)) < 1e-6)

namespace NSrvKernel::NDynamicBalancing {

inline TVector<TIntrusivePtr<TDynamicBackend>> FillBackends(
    TPessimizationTracker& tracker,
    size_t n,
    TVector<TAtomicSharedPtr<NSrvKernel::TBackendDescriptor>>* refs = nullptr
) {
    TVector<TAtomicSharedPtr<NSrvKernel::TBackendDescriptor>> backendRefs;
    if (!refs) {
        refs = &backendRefs;
    }
    for (size_t i = 0; i < n; i++) {
        refs->emplace_back(MakeAtomicShared<NSrvKernel::TBackendDescriptor>(ToString(i), nullptr, 1.0));
    }
    tracker.DiscoverNewBackends(*refs, nullptr);

    TVector<TIntrusivePtr<TDynamicBackend>> backends;
    for (size_t i = 0; i < n; i++) {
        backends.push_back(tracker.Backends().at(ToString(i))->Clone());
    }
    return backends;
}

inline void MakeBackendCritical(TDynamicBackend& backend, TConfig& config) {
    Y_ASSERT(config.has_fail_rate_check());

    for (size_t i = 0; i < config.fail_rate_check().min_requests(); i++) {
        TError error = Y_MAKE_ERROR(yexception{} << "error");
        backend.OnFailRequest(error, TDuration::Seconds(1));
    }
}

inline void AddSuccessfulRequests(TDynamicBackend& backend, size_t count, TDuration duration = TDuration::Seconds(1)) {
    for (size_t i = 0; i < count; ++i) {
        backend.OnCompleteRequest(duration);
    }
}

template <class T>
inline size_t CountBackendsByStatus(const TVector<T>& backends, TDynamicBackend::TStatus status) {
    size_t cnt = 0;
    for (const auto& backend : backends) {
        if (backend->Status == status) {
            cnt++;
        }
    }

    return cnt;
}

}
