#pragma once

#include <library/cpp/containers/comptrie/comptrie.h>
#include <library/cpp/uri/http_url.h>
#include <library/cpp/string_utils/url/url.h>

#include <mapreduce/yt/interface/client.h>
#include <mapreduce/yt/interface/protos/yamr.pb.h>

#include <wmconsole/version3/processors/indexing/library/sitetree.h>
#include <wmconsole/version3/processors/indexing/sitetree/protos/searchbase.pb.h>
#include <wmconsole/version3/protos/urltree.pb.h>

namespace NWebmaster {

inline void CommitTree(TSiteTreeBuilder &builder, THolder<TSiteTree> &siteTree) {
    TVector<TTreeRecord> siteStructure;
    builder.Commit(siteStructure);
    siteTree.Reset(new TSiteTree(siteStructure, builder.UserPatternMatcher));
}

struct TReduceBuildTrees : public NYT::IReducer<NYT::TTableReader<NProto::TPreparedUrl>, NYT::TTableWriter<NYT::TYamr>> {
    Y_SAVELOAD_JOB(Mode, ProductionTimestamp, AcceptanceTimestamp);

public:
    TReduceBuildTrees() = default;
    TReduceBuildTrees(time_t productionTimestamp, time_t acceptanceTimestamp, ETreeBuildMode mode = MODE_DEFAULT)
        : ProductionTimestamp(productionTimestamp)
        , AcceptanceTimestamp(acceptanceTimestamp)
        , Mode(mode)
    {
    }

    void Do(TReader *input, TWriter *output) override {
        const TString host = input->GetRow().GetHost();

        TSiteTreeBuilder builder(Mode);
        THolder<TSiteTree> siteTree;

        bool fake = true;
        for (; input->IsValid(); input->Next()) {
            const auto &row = input->GetRow();

            proto::urltree::RecordSourceInfo msg;
            Y_PROTOBUF_SUPPRESS_NODISCARD msg.ParseFromString(row.GetProto());

            if (row.GetPath() == "/") {
                builder.StartBuilding();
                TVector<TString> filters;
                for (int i = 0; i < msg.user_path_size(); i++) {
                    filters.push_back(msg.user_path(i));
                }
                if (!filters.empty()) {
                    builder.SetupUserPartitions(filters);
                }
            }

            if (msg.has_latest_url_info() || msg.url_info_size() > 0) {
                fake = false;
            }

            builder.AddPath(msg);
        }

        if (builder.BuildingInProgress()) { //in case if there aren't records from jupiter
            CommitTree(builder, siteTree);
        }

        if (!siteTree) {
            return;
        }

        TString stream;
        ProtoUrlTreeHost HostProto;
        HostProto.set_fake(fake);
        HostProto.set_hostname(host);
        HostProto.set_searchdb_production_timestamp(ProductionTimestamp);
        HostProto.set_searchdb_acceptance_timestamp(AcceptanceTimestamp);
        siteTree->Serialize(HostProto);
        Y_PROTOBUF_SUPPRESS_NODISCARD HostProto.SerializeToString(&stream);

        NYT::TYamr dstMsg;
        dstMsg.SetKey(host);
        dstMsg.SetSubkey("");
        dstMsg.SetValue(stream);
        output->AddRow(dstMsg);
    }

public:
    time_t ProductionTimestamp = 0;
    time_t AcceptanceTimestamp = 0;
    ETreeBuildMode Mode = MODE_DEFAULT;
};

} //namespace NWebmaster
