#include <balancer/modules/cookie_policy/ut_common/ut_common.h>

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

using namespace NModCookiePolicy;

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

        auto MakeCookieTypeOverrideConfig() {
            return MakeCombinedPolicy(R"=(instance={
                uuid="xxx";
                gdpr_server_cookie={
                    yyy={
                        mode='fix';
                    };
                };
                gdpr_controls={
                    tech_cookie_re='other_tech';
                };
            })=");
        }

        auto MakeCookies(TInstant now) {
            const auto y3 = TDuration::Days(3 * 365);
            const auto expires3y = *TExpires::FromInstant(now + TDuration::Days(3 * 365));
            return ToCookie({
                {.Name="i", .Expires=expires3y, .MaxAge=y3.Seconds()},
                {.Name="yandexuid", .Expires=expires3y, .MaxAge=y3.Seconds()},
                {.Name="whatever_other", .Expires=expires3y, .MaxAge=y3.Seconds()},
                {.Name="whatever_sess",},
                {.Name="whatever_del_max_age", .MaxAge=0},
                {.Name="whatever_del_expires", .Expires=TExpires::Past()},
            });
        }

        auto MakeFilteredCookies(TInstant now) {
            const auto y3 = TDuration::Days(3 * 365);
            const auto expires3y = *TExpires::FromInstant(now + TDuration::Days(3 * 365));
            return ToCookie({
                {.Name="i", .Expires=expires3y, .MaxAge=y3.Seconds()},
                {.Name="yandexuid", .Expires=expires3y, .MaxAge=y3.Seconds()},
                {.Name="whatever_sess",},
                {.Name="whatever_del_max_age", .MaxAge=0},
                {.Name="whatever_del_expires", .Expires=TExpires::Past()},
            });
        }
    }

    Y_UNIT_TEST(TestSkipNoGdpr) {
        TInstant now = TInstant::Seconds(1600092462);

        // No gdpr
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .Host={"yandex.eu"},
                .SetCookie=MakeCookies(now)
            },
            .Out={
                .SetCookie=MakeCookies(now),
                .ReqLog=" GdprDomain=1",
                .Stats=FixStatsNoGdpr({
                    {"cpol-xxx-gdpr-domain_summ", 1},
                    {"cpol-xxx-yyy-off_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookies(now).size()),
            },
        }));

        // The region is not gdpr
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .Host={"yandex.eu"},
                // {"BalancerVerHash":1361575,"Tstamp":1599858000,"IsGdpr":0,"IsGdprNoVpn":1}
                .Cookie={"gdpr=1; is_gdpr_b=CKeNUxBIKAE="},
                .SetCookie=MakeCookies(now)
            },
            .Out={
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepTech,},
                    .SafeValue={.Mode=EGdpr::KeepTech},
                },
                .Cookie={"gdpr=1; is_gdpr_b=CKeNUxBIKAE="},
                .SetCookie=MakeCookies(now),
                .ReqLog=" GdprDomain=1 Gdpr=1 IsGdprB=0,1",
                .Stats=FixStats({
                    {"cpol-xxx-gdpr-domain_summ", 1},
                    {"cpol-xxx-gdpr-geo-0_summ", 1},
                    {"cpol-xxx-gdpr-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-src-IsGdprB_summ", 1},
                    {"cpol-xxx-gdpr-safe-geo-0_summ", 1},
                    {"cpol-xxx-gdpr-safe-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-src-IsGdprB_summ", 1},
                    {"cpol-xxx-Gdpr-cookie_summ", 1},
                    {"cpol-xxx-IsGdprB-cookie_summ", 1},
                    {"cpol-xxx-yyy-off_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookies(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestSkipGdprKeepAll) {
        TInstant now = TInstant::Seconds(1600092462);
        // Gdpr but keeping all
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .Host={"yandex.eu"},
                .XYandexEURequest={"1"},
                .Cookie={"gdpr=0"},
                .SetCookie=MakeCookies(now)
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.IsGdpr=1},
                    .SafeValue={.IsGdpr=1},
                },
                .Cookie={"gdpr=0"},
                .SetCookie=MakeCookies(now),
                .ReqLog=" GdprDomain=1 Gdpr=0 XYandexEURequest=1",
                .Stats=FixStats({
                    {"cpol-xxx-gdpr-domain_summ", 1},
                    {"cpol-xxx-gdpr-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-mod-0_summ", 1},
                    {"cpol-xxx-gdpr-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-gdpr-safe-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-mod-0_summ", 1},
                    {"cpol-xxx-gdpr-safe-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-XYandexEURequest_summ", 1},
                    {"cpol-xxx-Gdpr-cookie_summ", 1},
                    {"cpol-xxx-yyy-off_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookies(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestSkipGdprNoPopup) {
        TInstant now = TInstant::Seconds(1600092462);
        // Gdpr but no popup
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .Host={"yandex.eu"},
                .XYandexEURequest={"1"},
                .SetCookie=MakeCookies(now)
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.IsGdpr=1},
                    .SafeValue={.IsGdpr=1},
                },
                .SetCookie=MakeCookies(now),
                .ReqLog=" GdprDomain=1 XYandexEURequest=1",
                .Stats=FixStats({
                    {"cpol-xxx-gdpr-domain_summ", 1},
                    {"cpol-xxx-gdpr-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-mod-0_summ", 1},
                    {"cpol-xxx-gdpr-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-gdpr-safe-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-mod-0_summ", 1},
                    {"cpol-xxx-gdpr-safe-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-XYandexEURequest_summ", 1},
                    {"cpol-xxx-yyy-off_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookies(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestDeleteOnGdprPopup) {
        TInstant now = TInstant::Seconds(1600092462);
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .XYandexEURequest={"1"},
                .Cookie={"gdpr_popup=1"},
                .SetCookie=MakeCookies(now)
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepTech, .IsGdpr=1},
                    .SafeValue={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                },
                .Cookie={"gdpr_popup=1"},
                .SetCookie=MakeFilteredCookies(now),
                .ReqLog=" GdprPopup=1 XYandexEURequest=1",
                .RespLog=" [cpol u:xxx-yyy fail+fix whatever_other=Drop:1!GdprDelete,]",
                .Stats=FixStats({
                    {"cpol-xxx-modified-resp_summ", 1},
                    {"cpol-xxx-gdpr-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-gdpr-safe-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-mod-0_summ", 1},
                    {"cpol-xxx-gdpr-safe-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-XYandexEURequest_summ", 1},
                    {"cpol-xxx-GdprPopup-cookie_summ", 1},
                    {"cpol-xxx-GdprPopup-noGdpr_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 1},
                    {"cpol-xxx-yyy-cookie-drop_summ", 1},
                    {"cpol-xxx-yyy-cookie-pass_summ", 2},
                    {"cpol-xxx-yyy-cookie-skip_summ", 3},
                    {"cpol-xxx-yyy-cookie-total_summ", 6},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookies(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestDeleteGdprKeepTech) {
        TInstant now = TInstant::Seconds(1600092462);
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .XYandexEURequest={"1"},
                .Cookie={"gdpr=1"},
                .SetCookie=MakeCookies(now)
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepTech, .IsGdpr=1},
                    .SafeValue={.Mode=EGdpr::KeepTech, .IsGdpr=1},
                },
                .Cookie={"gdpr=1"},
                .SetCookie=MakeFilteredCookies(now),
                .ReqLog=" Gdpr=1 XYandexEURequest=1",
                .RespLog=" [cpol u:xxx-yyy fail+fix whatever_other=Drop:1!GdprDelete,]",
                .Stats=FixStats({
                    {"cpol-xxx-modified-resp_summ", 1},
                    {"cpol-xxx-gdpr-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-gdpr-safe-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-XYandexEURequest_summ", 1},
                    {"cpol-xxx-Gdpr-cookie_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 1},
                    {"cpol-xxx-yyy-cookie-drop_summ", 1},
                    {"cpol-xxx-yyy-cookie-pass_summ", 2},
                    {"cpol-xxx-yyy-cookie-skip_summ", 3},
                    {"cpol-xxx-yyy-cookie-total_summ", 6},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookies(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestDeleteGdprKeepTechDryRun) {
        TInstant now = TInstant::Seconds(1600092462);
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(false),
                .Now=now,
                .XYandexEURequest={"1"},
                .Cookie={"gdpr=1"},
                .SetCookie=MakeCookies(now)
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepTech, .IsGdpr=1},
                    .SafeValue={.Mode=EGdpr::KeepTech, .IsGdpr=1},
                },
                .Cookie={"gdpr=1"},
                .SetCookie=MakeCookies(now),
                .ReqLog=" Gdpr=1 XYandexEURequest=1",
                .RespLog=" [cpol u:xxx-yyy fail+dryRun whatever_other=Drop:1!GdprDelete,]",
                .Stats=FixStats({
                    {"cpol-xxx-gdpr-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-gdpr-safe-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-XYandexEURequest_summ", 1},
                    {"cpol-xxx-Gdpr-cookie_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 1},
                    {"cpol-xxx-yyy-cookie-drop-dryRun_summ", 1},
                    {"cpol-xxx-yyy-cookie-pass_summ", 2},
                    {"cpol-xxx-yyy-cookie-skip_summ", 3},
                    {"cpol-xxx-yyy-cookie-total_summ", 6},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookies(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestCookieTypeOverride) {
        TInstant now = TInstant::Seconds(1600092462);

        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .Now=now,
                .Path="/",
                .Host={"yandex.eu"},
                .XYandexEURequest={"1"},
                .Cookie={"gdpr=1"},
                .SetCookie=ToCookie({{.Name="other_tech", .MaxAge=1}})
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepTech, .IsGdpr=1},
                    .SafeValue={.Mode=EGdpr::KeepTech, .IsGdpr=1},
                },
                .Cookie={"gdpr=1"},
                .ReqLog=" GdprDomain=1 Gdpr=1 XYandexEURequest=1",
                .RespLog=" [cpol u:xxx-yyy fail+fix other_tech=Drop:1!GdprDelete,]",
                .Stats=FixStats({
                    {"cpol-xxx-modified-resp_summ", 1},
                    {"cpol-xxx-gdpr-domain_summ", 1},
                    {"cpol-xxx-gdpr-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-gdpr-safe-geo-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-mod-1_summ", 1},
                    {"cpol-xxx-gdpr-safe-src-XYandexEURequest_summ", 1},
                    {"cpol-xxx-XYandexEURequest_summ", 1},
                    {"cpol-xxx-Gdpr-cookie_summ", 1},
                    {"cpol-xxx-yyy-cookie-total_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 1},
                    {"cpol-xxx-yyy-cookie-drop_summ", 1},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, 1),
            },
        }));

        const auto out = TCPTestResult{
            .GeoCache={.XYandexEURequest=1},
            .Gdpr={
                .Value={.Mode=EGdpr::KeepTech, .IsGdpr=1},
                .SafeValue={.Mode=EGdpr::KeepTech, .IsGdpr=1},
            },
            .Cookie={"gdpr=1"},
            .SetCookie=ToCookie({{.Name="other_tech", .MaxAge=1}}),
            .ReqLog=" GdprDomain=1 Gdpr=1 XYandexEURequest=1",
            .Stats=FixStats({
                {"cpol-xxx-gdpr-domain_summ", 1},
                {"cpol-xxx-gdpr-geo-1_summ", 1},
                {"cpol-xxx-gdpr-mod-1_summ", 1},
                {"cpol-xxx-gdpr-src-XYandexEURequest_summ", 1},
                {"cpol-xxx-gdpr-safe-geo-1_summ", 1},
                {"cpol-xxx-gdpr-safe-mod-1_summ", 1},
                {"cpol-xxx-gdpr-safe-src-XYandexEURequest_summ", 1},
                {"cpol-xxx-XYandexEURequest_summ", 1},
                {"cpol-xxx-Gdpr-cookie_summ", 1},
                {"cpol-xxx-yyy-cookie-pass_summ", 1},
                {"cpol-xxx-yyy-cookie-total_summ", 1},
                {"cpol-xxx-yyy-pass_summ", 1},
                {"cpol-xxx-yyy-total_summ", 1},
            }, 1),
        };

        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeCookieTypeOverrideConfig(),
                .Now=now,
                .Path="/",
                .Host={"yandex.eu"},
                .XYandexEURequest={"1"},
                .Cookie={"gdpr=1"},
                .SetCookie=ToCookie({{.Name="other_tech", .MaxAge=1}})
            },
            .Out=out,
        }));

        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeConfig(true),
                .GdprCtl=R"=({"tech_cookie_re": "other_tech"})=",
                .Now=now,
                .Path="/",
                .Host={"yandex.eu"},
                .XYandexEURequest={"1"},
                .Cookie={"gdpr=1"},
                .SetCookie=ToCookie({{.Name="other_tech", .MaxAge=1}})
            },
            .Out=out,
        }));
    }
}
