#include "p_gdpr_lifetime.h"

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

namespace NModCookiePolicy {
    TPolicyGdprLifetime::TPolicyGdprLifetime(TString name, const TPolicyGdprLifetimeCfg& cfg)
        : ICookiePolicy(name, cfg.mode())
        , Cfg_(cfg)
    {
        NGdprCookie::InitCookieRegistry(false);
    }

    bool TPolicyGdprLifetime::MatchRequest(const TPolicyArgs& args) const noexcept {
        return args.Descr.Properties->Gdpr.Value.IsGdpr;
    }

    bool TPolicyGdprLifetime::MatchResponseCookie(const TSetCookie& c, const TPolicyArgs& args) const noexcept {
        // A permanent cookie which is not a deletion
        return (c.Expires || c.MaxAge) && !HasDeletion(c, args.Descr.Properties->Start);
    }

    TMaybe<ICookiePolicy::TAction> TPolicyGdprLifetime::ApplyToResponseCookie(
        TResponseCookieView c, const TPolicyArgs& args) const noexcept
    {
        const auto& cc = c.Const();
        TAction errs;

        if (cc.Expires) {
            const auto expiresMax = NGdprCookie::TMaxAllowedExpires::Get(args.Descr.Properties->Start);
            if (cc.Expires.Get() > expiresMax) {
                errs.Reasons.Set(EResponseCookieReason::BigLifetime);
                if (!args.DryRun) {
                    c.Mutable().Expires = expiresMax;
                }
            }
        }

        if (cc.MaxAge) {
            const auto maxMaxAge = NGdprCookie::MaxAllowedAge.Seconds();
            if (*cc.MaxAge > maxMaxAge) {
                errs.Reasons.Set(EResponseCookieReason::BigLifetime);
                if (!args.DryRun) {
                    c.Mutable().MaxAge = maxMaxAge;
                }
            }
        }

        if (errs.Reasons) {
            return errs;
        }

        return Nothing();
    }
}
