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

#include <balancer/kernel/cookie/gdpr/lifetime.h>

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

using namespace NModCookiePolicy;

Y_UNIT_TEST_SUITE(TPolicyPersistentLifetimeTest) {
    namespace {
        auto MakeCookie(TInstant now) {
            const auto s1 = TDuration::Seconds(1);
            const auto exp1s = *TExpires::FromInstant(now + s1);
            const auto y10 = 10 * 365 * TDuration::Days(1);
            const auto exp10y = *TExpires::FromInstant(now + y10);

            return ToCookie({
                {.Name="yp_long", .Expires=exp10y, .MaxAge=y10.Seconds()},
                {.Name="yp_short", .Expires=exp1s, .MaxAge=1},
                {.Name="yp_del", .Expires=TExpires::Min(), .MaxAge=0},
                {.Name="yp_sess",},
                {.Name="other",},
            });
        }

        auto MakeBigLimitsConfig(bool fix) {
            return MakeCombinedPolicy(Sprintf(R"=(instance={
                uuid="xxx";
                persistent_lifetime={
                    yyy={
                        name_re="yp.*";
                        max_age_min=126144000;
                        gdpr_max_age_min=46656000;
                        %s
                    };
                };
            })=", (fix ? "mode='fix';" : "")));
        }

        auto MakeSmallLimitsConfig(bool fix) {
            return MakeCombinedPolicy(Sprintf(R"=(instance={
                uuid="xxx";
                persistent_lifetime={
                    yyy={
                        name_re="yp.*";
                        max_age_min=15552000;
                        gdpr_max_age_min=15552000;
                        %s
                    };
                };
            })=", (fix ? "mode='fix';" : "")));
        }
    }

    Y_UNIT_TEST(TestBigLimits) {
        const auto now = TInstant::Seconds(1596470989);
        const auto y4 = 4 * 365 * TDuration::Days(1);
        const auto exp4y = *TExpires::FromInstant(now + y4);
        const auto y10 = 10 * 365 * TDuration::Days(1);
        const auto exp10y = *TExpires::FromInstant(now + y10);

        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeBigLimitsConfig(true),
                .Now=now,
                .SetCookie=MakeCookie(now),
            },
            .Out={
                .SetCookie=ToCookie({
                    {.Name="yp_long", .Expires=exp10y, .MaxAge=y10.Seconds()},
                    {.Name="yp_short", .Expires=exp4y, .MaxAge=y4.Seconds()},
                    {.Name="yp_del", .Expires=TExpires::Min(), .MaxAge=0},
                    {.Name="other",},
                }),
                .RespLog=" [cpol u:xxx-yyy fail+fix"
                         " yp_short=Fix:1!SmallLifetime,"
                         " yp_sess=Drop:1!NotPersistentLifetime,]",
                .Stats=FixStatsNoGdpr({
                    {"cpol-xxx-modified-resp_summ", 1},
                    {"cpol-xxx-yyy-cookie-drop_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 2},
                    {"cpol-xxx-yyy-cookie-fix_summ", 1},
                    {"cpol-xxx-yyy-cookie-pass_summ", 1},
                    {"cpol-xxx-yyy-cookie-skip_summ", 2},
                    {"cpol-xxx-yyy-cookie-total_summ", 5},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookie(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestBigLimitsDryRun) {
        const auto now = TInstant::Seconds(1596470989);
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeBigLimitsConfig(false),
                .Now=now,
                .SetCookie=MakeCookie(now),
            },
            .Out={
                .SetCookie=MakeCookie(now),
                .RespLog=" [cpol u:xxx-yyy fail+dryRun"
                         " yp_short=Fix:1!SmallLifetime,"
                         " yp_sess=Drop:1!NotPersistentLifetime,]",
                .Stats=FixStatsNoGdpr({
                    {"cpol-xxx-yyy-cookie-drop-dryRun_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 2},
                    {"cpol-xxx-yyy-cookie-pass_summ", 1},
                    {"cpol-xxx-yyy-cookie-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-cookie-skip_summ", 2},
                    {"cpol-xxx-yyy-cookie-total_summ", 5},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookie(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestBigLimitsGdpr) {
        const auto now = TInstant::Seconds(1596470989);
        const auto y10 = 10 * 365 * TDuration::Days(1);
        const auto exp10y = *TExpires::FromInstant(now + y10);
        const auto y1_5 = 180 * 3 * TDuration::Days(1);
        const auto exp1_5y = *TExpires::FromInstant(now + y1_5);

        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeBigLimitsConfig(true),
                .GeoCache={.XYandexEURequest=1},
                .Now=now,
                .SetCookie=MakeCookie(now),
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                    .SafeValue={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                },
                .SetCookie=ToCookie({
                    {
                        .Name="yp_long",
                        .Expires=exp10y,
                        .MaxAge=y10.Seconds(),
                    },
                    {
                        .Name="yp_short",
                        .Expires=exp1_5y,
                        .MaxAge=y1_5.Seconds(),
                    },
                    {.Name="yp_del", .Expires=TExpires::Min(), .MaxAge=0},
                    {.Name="other",},
                }),
                .RespLog=" [cpol u:xxx-yyy fail+fix"
                         " yp_short=Fix:1!SmallLifetime,"
                         " yp_sess=Drop:1!NotPersistentLifetime,]",
                .Stats=FixStats({
                    {"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-modified-resp_summ", 1},
                    {"cpol-xxx-yyy-cookie-drop_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 2},
                    {"cpol-xxx-yyy-cookie-fix_summ", 1},
                    {"cpol-xxx-yyy-cookie-pass_summ", 1},
                    {"cpol-xxx-yyy-cookie-skip_summ", 2},
                    {"cpol-xxx-yyy-cookie-total_summ", 5},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookie(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestBigLimitsGdprDryRun) {
        const auto now = TInstant::Seconds(1596470989);
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeBigLimitsConfig(false),
                .GeoCache={.XYandexEURequest=1},
                .Now=now,
                .SetCookie=MakeCookie(now),
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                    .SafeValue={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                },
                .SetCookie=MakeCookie(now),
                .RespLog=" [cpol u:xxx-yyy fail+dryRun"
                         " yp_short=Fix:1!SmallLifetime,"
                         " yp_sess=Drop:1!NotPersistentLifetime,]",
                .Stats=FixStats({
                    {"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-yyy-cookie-drop-dryRun_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 2},
                    {"cpol-xxx-yyy-cookie-pass_summ", 1},
                    {"cpol-xxx-yyy-cookie-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-cookie-skip_summ", 2},
                    {"cpol-xxx-yyy-cookie-total_summ", 5},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookie(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestSmallLimitsGdpr) {
        const auto now = TInstant::Seconds(1596470989);
        const auto m6 = 6 * 30 * TDuration::Days(1);
        const auto exp6m = *TExpires::FromInstant(now + m6);
        const auto y10 = 10 * 365 * TDuration::Days(1);
        const auto exp10y = *TExpires::FromInstant(now + y10);

        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeSmallLimitsConfig(true),
                .GeoCache={.XYandexEURequest=1},
                .Now=now,
                .SetCookie=MakeCookie(now),
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                    .SafeValue={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                },
                .SetCookie=ToCookie({
                    {.Name="yp_long", .Expires=exp10y, .MaxAge=y10.Seconds(),},
                    {.Name="yp_short", .Expires=exp6m, .MaxAge=m6.Seconds(),},
                    {.Name="yp_del", .Expires=TExpires::Min(), .MaxAge=0},
                    {.Name="other",},
                }),
                .RespLog=" [cpol u:xxx-yyy fail+fix"
                         " yp_short=Fix:1!SmallLifetime,"
                         " yp_sess=Drop:1!NotPersistentLifetime,]",
                .Stats=FixStats({
                    {"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-modified-resp_summ", 1},
                    {"cpol-xxx-yyy-cookie-drop_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 2},
                    {"cpol-xxx-yyy-cookie-pass_summ", 1},
                    {"cpol-xxx-yyy-cookie-fix_summ", 1},
                    {"cpol-xxx-yyy-cookie-skip_summ", 2},
                    {"cpol-xxx-yyy-cookie-total_summ", 5},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookie(now).size()),
            },
        }));
    }

    Y_UNIT_TEST(TestSmallLimitsGdprDryRun) {
        const auto now = TInstant::Seconds(1596470989);
        Y_COOKIE_POLICY_TEST_POLICY((TPolicyTestCase{
            .In={
                .Cfg=MakeSmallLimitsConfig(false),
                .GeoCache={.XYandexEURequest=1},
                .Now=now,
                .SetCookie=MakeCookie(now),
            },
            .Out={
                .GeoCache={.XYandexEURequest=1},
                .Gdpr={
                    .Value={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                    .SafeValue={.Mode=EGdpr::KeepAll, .IsGdpr=1},
                },
                .SetCookie=MakeCookie(now),
                .RespLog=" [cpol u:xxx-yyy fail+dryRun"
                         " yp_short=Fix:1!SmallLifetime,"
                         " yp_sess=Drop:1!NotPersistentLifetime,]",
                .Stats=FixStats({
                    {"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-yyy-cookie-drop-dryRun_summ", 1},
                    {"cpol-xxx-yyy-cookie-fail_summ", 2},
                    {"cpol-xxx-yyy-cookie-pass_summ", 1},
                    {"cpol-xxx-yyy-cookie-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-cookie-skip_summ", 2},
                    {"cpol-xxx-yyy-cookie-total_summ", 5},
                    {"cpol-xxx-yyy-fail_summ", 1},
                    {"cpol-xxx-yyy-fix-dryRun_summ", 1},
                    {"cpol-xxx-yyy-total_summ", 1},
                }, MakeCookie(now).size()),
            },
        }));
    }
}
