#pragma once

#include "utils.h"

#include <balancer/modules/cookie_policy/common/cookie_policy.cfgproto.pb.h>
#include <balancer/modules/cookie_policy/common/gdpr_controls.h>
#include <balancer/modules/cookie_policy/common/mode_controls.h>
#include <balancer/modules/cookie_policy/common/utils.h>

#include <library/cpp/testing/unittest/registar.h>

namespace NModCookiePolicy {
    using namespace NGdprCookie;

    constexpr TStringBuf FirefoxUA = "Mozilla/5.0 (Android 6.0; Mobile; rv:68.0) Gecko/68.0 Firefox/68.0";
    constexpr TStringBuf ChromimUA =
        "Mozilla/5.0 (Linux; Android 6.0; M5 Note) AppleWebKit/537.36 (KHTML, like Gecko)"
        " Chrome/77.0.3770.143 Mobile Safari/537.36";

    template <class TCol>
    TCol Sorted(TCol c) noexcept {
        Sort(c);
        return c;
    }

    struct TCPTestInput {
        TModuleConfig Cfg;
        TString ModeCtl;
        TString GdprCtl;

        TGdprCache GeoCache;

        TInstant Now;
        ui64 Random = 0;

        TString Path;

        TStrVec Host;
        TStrVec UserAgent;
        TStrVec XYandexRandomUid;
        TStrVec XYandexEURequest;
        TStrVec XIpProperties;
        TStrVec Cookie;

        TStrVec SetCookie;

        bool IsSecure = true;
        bool WithStats = true;
    };

    struct TCPTestResult {
        TGdprCache GeoCache;
        TGdpr Gdpr;

        TStrVec Cookie;
        TStrVec SetCookie;

        TString ReqLog;
        TString RespLog;
        TStatsVec Stats;

    public:
        Y_BALANCER_TUPLE_EQ(
            TCPTestResult,
            std::ref(Cookie),
            std::ref(SetCookie),
            Gdpr,
            GeoCache,
            std::ref(ReqLog),
            std::ref(RespLog),
            Sorted(Stats)
        )
    };

    struct TPolicyTestCase {
        TCPTestInput In;
        TCPTestResult Out;
    };

    TCPTestResult TestCookiePolicy(const TCPTestInput& inp);

    TString ToOneCookie(const TSetCookie& c);
    TStrVec ToCookie(const TVector<TSetCookie>& c);

    TSetCookie IsGdprSetCookie(bool value, TInstant now, std::string domain, ESameSite ss);
    TSetCookie IsGdprBSetCookie(TIsGdprB value, TInstant now, std::string domain, ESameSite ss);

    TStatsVec FixStats(TStatsVec v, ui32 cookieCnt);
    TStatsVec FixStatsNoGdpr(TStatsVec v, ui32 cookieCnt);

    TModuleConfig MakeCombinedPolicy(TString raw);

    void DoTestPolicy(const TPolicyTestCase& c, TSourceLocation loc);
#define Y_COOKIE_POLICY_TEST_POLICY(c) DoTestPolicy(c, __LOCATION__)
}
