#include <balancer/modules/cookie_policy/ut_common/ut_common.h>
#include <balancer/kernel/helpers/yuid.h>

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

using namespace NModCookiePolicy;

Y_UNIT_TEST_SUITE(TPolicyYandexuidCreateTest) {
    namespace {
        auto MakeConfig(bool fix) {
            return MakeCombinedPolicy(Sprintf(R"=(instance={
                uuid="xxx";
                yandexuid_create={
                    yyy={
                        %s
                    };
                };
            })=", (fix ? "mode='fix';" : "")));
        }
    }

    Y_UNIT_TEST(TestCreate) {
        const auto now = TInstant::Seconds(1596470989);
        const auto rnd = 555555555;
        const auto val = GetYuid(rnd, now);

        const auto cc = ToCookie({TSetCookie{.Name="other"}});

        for (auto [ua, ss] : std::initializer_list<std::pair<TStrVec, ESameSite>>{
            {{}, ESameSite::Undefined},
            {{ToString(FirefoxUA)}, ESameSite::Undefined},
            {{ToString(ChromimUA)}, ESameSite::None},
        }) {
            Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
                .In={
                    .Cfg=MakeConfig(true),
                    .Now=now,
                    .Random=rnd,
                    .Host={"www.yandex.ru"},
                    .UserAgent={ua},
                    .Cookie={"xxx=yyy"},
                    .SetCookie=ToCookie({TSetCookie{.Name="other"}}),
                },
                .Out={
                    .Cookie={"xxx=yyy; yandexuid=" + val},
                    .SetCookie=ToCookie({
                        TSetCookie{.Name="other"},
                        TSetCookie{
                            .Name="yandexuid",
                            .Value=TBlob::NoCopy(val.data(), val.size()),
                            .Path="/",
                            .Domain=".yandex.ru",
                            .Expires=TExpires::FromInstant(now + TDuration::Days(365*10)),
                            .SameSite=ss,
                            .Secure=true,
                        }
                    }),
                    .ReqLog=" [cpol-req u:xxx-yyy fail+fix yandexuid=Add:1!Create,]",
                    .RespLog=" [cpol u:xxx-yyy fail+fix yandexuid=Add:1!Create,]",
                    .Stats=FixStatsNoGdpr({
                        {"cpol-xxx-modified-req_summ", 1},
                        {"cpol-xxx-modified-resp_summ", 1},
                        {"cpol-xxx-yyy-cookie-skip_summ", 1},
                        {"cpol-xxx-yyy-cookie-add_summ", 1},
                        {"cpol-xxx-yyy-cookie-total_summ", 1},
                        {"cpol-xxx-yyy-req-cookie-add_summ", 1},
                        {"cpol-xxx-yyy-fail_summ", 1},
                        {"cpol-xxx-yyy-fix_summ", 1},
                        {"cpol-xxx-yyy-total_summ", 1},
                    }, 1),
                },
            }));

            // Using X-Yandex-RandomUID if available
            Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
                .In={
                    .Cfg=MakeConfig(true),
                    .Now=now,
                    .Random=rnd,
                    .Host={"www.yandex.ru"},
                    .UserAgent={ua},
                    .XYandexRandomUid={"111111111111111111"},
                    .Cookie={"xxx=yyy"},
                    .SetCookie=ToCookie({TSetCookie{.Name="other"}}),
                },
                .Out={
                    .Cookie={"xxx=yyy; yandexuid=111111111111111111"},
                    .SetCookie=ToCookie({
                        TSetCookie{.Name="other"},
                        TSetCookie{
                            .Name="yandexuid",
                            .Value=TBlob::FromString("111111111111111111"),
                            .Path="/",
                            .Domain=".yandex.ru",
                            .Expires=TExpires::FromInstant(now + TDuration::Days(365*10)),
                            .SameSite=ss,
                            .Secure=true,
                        }
                    }),
                    .ReqLog=" [cpol-req u:xxx-yyy fail+fix yandexuid=Add:1!Create,]",
                    .RespLog=" [cpol u:xxx-yyy fail+fix yandexuid=Add:1!Create,]",
                    .Stats=FixStatsNoGdpr({
                        {"cpol-xxx-modified-req_summ", 1},
                        {"cpol-xxx-modified-resp_summ", 1},
                        {"cpol-xxx-yyy-cookie-skip_summ", 1},
                        {"cpol-xxx-yyy-cookie-add_summ", 1},
                        {"cpol-xxx-yyy-cookie-total_summ", 1},
                        {"cpol-xxx-yyy-req-cookie-add_summ", 1},
                        {"cpol-xxx-yyy-fail_summ", 1},
                        {"cpol-xxx-yyy-fix_summ", 1},
                        {"cpol-xxx-yyy-total_summ", 1},
                    }, 1),
                },
            }));
        }

        // Bad host
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .Random=rnd,
                .SetCookie=ToCookie({TSetCookie{.Name="other"}}),
            },
            .Out={
                .SetCookie=ToCookie({TSetCookie{.Name="other"}}),
                .Stats=FixStatsNoGdpr({
                    {"cpol-xxx-yyy-off_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, 1),
            },
        }));

        // Exists (even if invalid)
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .Random=rnd,
                .Host={"yandex.ru"},
                .Cookie={"yandexuid=xxx"},
            },
            .Out={
                .Cookie={"yandexuid=xxx"},
                .Stats=FixStatsNoGdpr({
                    {"cpol-xxx-yyy-pass_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, 0),
            },
        }));

        // The backend has priority
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .Random=rnd,
                .Host={"yandex.ru"},
                .SetCookie=ToCookie({TSetCookie{.Name="yandexuid",.Value=NCookie::FromStringBuf("xxx")}}),
            },
            .Out={
                .Cookie={"yandexuid=" + val},
                .SetCookie=ToCookie({TSetCookie{.Name="yandexuid",.Value=NCookie::FromStringBuf("xxx")}}),
                .ReqLog=" [cpol-req u:xxx-yyy fail+fix yandexuid=Add:1!Create,]",
                .Stats=FixStatsNoGdpr({
                    {"cpol-xxx-modified-req_summ", 1},
                    {"cpol-xxx-yyy-cookie-pass_summ", 1},
                    {"cpol-xxx-yyy-cookie-total_summ", 1},
                    {"cpol-xxx-yyy-req-cookie-add_summ", 1},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, 1),
            },
        }));
    }

    Y_UNIT_TEST(TestCreateDryRun) {
        const auto now = TInstant::Seconds(1596470989);
        const auto rnd = 555555555;

        const auto cc = ToCookie({TSetCookie{.Name="other"}});

        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(false),
                .Now=now,
                .Random=rnd,
                .Host={"www.yandex.ru"},
                .Cookie={"xxx=yyy"},
                .SetCookie=ToCookie({TSetCookie{.Name="other"}}),
            },
            .Out={
                .Cookie={"xxx=yyy"},
                .SetCookie=ToCookie({TSetCookie{.Name="other"}}),
                .ReqLog=" [cpol-req u:xxx-yyy fail+dryRun yandexuid=Add:1!Create,]",
                .RespLog=" [cpol u:xxx-yyy fail+dryRun yandexuid=Add:1!Create,]",
                .Stats=FixStatsNoGdpr({
                    {"cpol-xxx-yyy-cookie-skip_summ", 1},
                    {"cpol-xxx-yyy-cookie-add-dryRun_summ", 1},
                    {"cpol-xxx-yyy-cookie-total_summ", 1},
                    {"cpol-xxx-yyy-req-cookie-add-dryRun_summ", 1},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, 1),
            },
        }));

        // The backend has priority
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(false),
                .Now=now,
                .Random=rnd,
                .Host={"yandex.ru"},
                .SetCookie=ToCookie({TSetCookie{.Name="yandexuid",.Value=NCookie::FromStringBuf("xxx")}}),
            },
            .Out={
                .SetCookie=ToCookie({TSetCookie{.Name="yandexuid",.Value=NCookie::FromStringBuf("xxx")}}),
                .ReqLog=" [cpol-req u:xxx-yyy fail+dryRun yandexuid=Add:1!Create,]",
                .Stats=FixStatsNoGdpr({
                    {"cpol-xxx-yyy-cookie-pass_summ", 1},
                    {"cpol-xxx-yyy-cookie-total_summ", 1},
                    {"cpol-xxx-yyy-req-cookie-add-dryRun_summ", 1},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, 1),
            },
        }));
    }
}
