#pragma once
#include <saas/rtyserver/unistat_signals/signals.h>
#include <saas/util/logging/tskv_log.h>
#include <kernel/searchlog/searchlog.h>
#include <library/cpp/logger/global/common.h>
#include <library/cpp/logger/log.h>

class TRTYIndexLog: public TSearchLog {
public:
    TRTYIndexLog(const TString& logType, ELogPriority priority = LOG_MAX_PRIORITY, size_t queueLen = 0)
        : TSearchLog(logType, priority, queueLen)
        , Priority(priority)
    {
    }
    ELogPriority GetPriority() const {
        return Priority;
    }
private:
    ELogPriority Priority;
};

template<>
class TSingletonTraits < TLoggerOperator<TRTYIndexLog>::TPtr > {
public:
    static const size_t Priority = NLoggingImpl::SingletonPriority;
};

inline void QueueReplyLog(const TString& serviceName, const ui64 messageId, const TString& url, const TString& status, const ui32 httpCode, const ui64 duration, const TString& errorMessage) {
    auto* log = TLoggerOperator<TRTYIndexLog>::Get();
    if (log && !log->IsNullLog() && (log->GetPriority() >= TLOG_INFO || (log->GetPriority() >= TLOG_ERR && httpCode >= 300))) {
        NUtil::TTSKVRecord tskv("saas-rty-index-log");
        tskv.AddIsoEventTime().Add("key", url).Add("id", (messageId)).Add("reply", status).Add("http_code", httpCode).ForceAdd("duration", duration);
        tskv.Add("service", serviceName);
        if (httpCode >= 300) {
            tskv.Add("error_message", errorMessage);
        }
        *log << tskv.ToString() << Endl;
    }
}

inline void QueueReplyLogWithUnistat(const TString& serviceName, const TMaybe<TString>& documentUrlMaybe, const ui64 messageId, const TString& status, const ui32 httpCode,
    const ui64 duration, const TString& errorMessage)
{
    const TString& docUrl = documentUrlMaybe.GetOrElse(Default<TString>());
    QueueReplyLog(serviceName, messageId, docUrl, status, httpCode, duration, errorMessage);
    TSaasRTYServerSignals::DoUnistatRecordIndex(httpCode, duration);
}

template<typename R, typename M>
inline void QueueMessageReqLog(const TString& serviceName, const R& req, const M& message, const TString& queueName, const TString& status) {
    auto* log = TLoggerOperator<TRTYIndexLog>::Get();
    if (log && !log->IsNullLog() && log->GetPriority() >= TLOG_INFO) {
        NUtil::TTSKVRecord tskv("saas-rty-index-log");
        tskv.AddIsoEventTime().Add("ip", req->RemoteHost()).Add("request_id", req->RequestId());
        tskv.ForceAdd("id", message.GetMessageId()).Add("message_type", int(message.GetMessageType()));
        if (message.HasDocument())
            tskv.Add("key", message.GetDocument().GetUrl()).Add("size", (message.GetDocument().GetBody().size())).Add("keyprefix", message.GetDocument().GetKeyPrefix());
        tskv.Add("indexer", queueName).Add("status", status);
        tskv.Add("service", serviceName);
        *log << tskv.ToString() << Endl;
    }
}

template<typename T>
inline void QueueDocumentLog(const TString& serviceName, const T& document, const TString& indexer, const TString& status) {
    auto* log = TLoggerOperator<TRTYIndexLog>::Get();
    if (log && !log->IsNullLog() && log->GetPriority() >= TLOG_INFO) {
        NUtil::TTSKVRecord tskv("saas-rty-index-log");
        tskv.AddIsoEventTime().Add("key", document.GetDocSearchInfo().GetUrl()).Add("keyprefix", document.GetDocSearchInfo().GetKeyPrefix()).Add("indexer", indexer).Add("status", status);
        tskv.Add("service", serviceName);
        *log << tskv.ToString() << Endl;
    }
}

inline void DocumentLog(const TString& serviceName, const TString& url, const ui64 kps, const TString& indexer, const TString& status) {
    auto* log = TLoggerOperator<TRTYIndexLog>::Get();
    if (log && !log->IsNullLog() && log->GetPriority() >= TLOG_INFO) {
        NUtil::TTSKVRecord tskv("saas-rty-index-log");
        tskv.AddIsoEventTime().Add("key", url).Add("keyprefix", kps).Add("indexer", indexer).Add("status", status);
        tskv.Add("service", serviceName);
        *log << tskv.ToString() << Endl;
    }
}
