#pragma once

#include <saas/searchproxy/common/cgi.h>

#include <search/request/data/reqdata.h>

#include <library/cpp/tvmauth/client/facade.h>

#include <util/generic/maybe.h>
#include <util/generic/hash_set.h>
#include <library/cpp/cgiparam/cgiparam.h>

namespace NSearchProxy {

    struct TTvmAuthResult {
        enum EStatus {
            Initial /* "initial" */,
            NoServiceTicketFromClient /* "no_ticket" */,
            NoUserTicketFromClient /* "no_user_ticket" */,
            BadServiceTicket /* "bad_ticket" */,
            BadUserTicket /* "bad_user_ticket" */,
            NotAllowedSrcClientId /* "bad_src_id" */,
            NotAllowedUid /* "bad_uid" */,
            Authorized /* "ok" */
        };

        EStatus Status = Initial;
        TMaybe<ui32> SrcId;
        TMaybe<ui64> Uid;

        bool IsAuthorized() const {
            return Status == Authorized;
        }
    };

    class ITvmClient: public TThrRefBase {
    public:
        virtual ~ITvmClient() {
        }

        virtual TMaybe<ui32> CheckServiceTicket(const TString&) const = 0;
        virtual TMaybe<ui64> CheckUserTicket(const TString&) const = 0;
    };

    using ITvmClientPtr = TIntrusivePtr<ITvmClient>;

    ITvmClientPtr CreateMultiTvmClient(TVector<ITvmClientPtr> clients);

    struct TTvmTraits {
        static bool IsAuthForced(const TCgiParameters& cgi);

        static TString GetServiceTicketString(const TSearchRequestData& rd);
        static TString GetUserTicketString(const TSearchRequestData& rd);

        struct TTickets {
            TString ServiceTicket;
            TString UserTicket;
        };

        struct TClients {
            NSearchProxy::ITvmClientPtr Main;
            NSearchProxy::ITvmClientPtr FlowMirror;
        };

        static TTickets GetTickets(const TSearchRequestData& rd);
    };

    struct TTvmAuthParams {
        const TTvmTraits::TClients& Clients;
        TTvmTraits::TTickets Tickets;
        const THashSet<ui32>& AllowedSourceIds;
        ui32 TvmProxyId = 0;
        THashSet<ui64> AllowedUids;
    };

    TTvmAuthResult AuthorizeTvm(const TTvmAuthParams& params);

}
