#include <util/digest/fnv.h>
#include <util/generic/hash_set.h>
#include <util/generic/size_literals.h>

#include <wmconsole/version3/library/jupiter/jupiter.h>
#include <wmconsole/version3/wmcutil/hostid.h>
#include <wmconsole/version3/wmcutil/url.h>
#include <wmconsole/version3/wmcutil/yt/triggers.h>
#include <robot/library/yt/static/command.h>
#include <wmconsole/version3/wmcutil/yt/yt_runner.h>
#include <wmconsole/version3/processors/tools/IKS/utils/canonizer.h>
#include <wmconsole/version3/processors/tools/host2vec/utils/utils.h>
#include <wmconsole/version3/processors/user_sessions/library/regions_limiter.h>
#include <wmconsole/version3/processors/user_sessions/niche2/conf/config.h>
#include <wmconsole/version3/processors/user_sessions/niche2/preparation/tables.pb.h>
#include <robot/library/yt/static/tags.h>
#include <library/cpp/compute_graph/compute_graph.h>
#include <library/cpp/text_processing/tokenizer/tokenizer.h>
#include <wmconsole/version3/library/dssm/dssm_utils.h>
#include <wmconsole/version3/processors/user_sessions/library/utils.h>
#include <wmconsole/version3/processors/user_sessions/protos/user_sessions.pb.h>

#include <wmconsole/version3/processors/user_sessions/niche/conf/config.h>


#include "task_apply_hash_to_clusters.h"

namespace NWebmaster {
namespace NNiche2 {
using namespace NJupiter;
using namespace NProto;

struct THashSearchshareMapper:
    public NYT::IMapper<NYT::TTableReader<NYT::TNode>, NYT::TTableWriter<TQueryToCluster>> {
    void Do(TReader *input, TWriter *output) override {
        TQueryToCluster res;
        for (; input->IsValid(); input->Next()) {
            const auto &row = input->GetRow();
            auto queryEntity = row["query"];
            if (queryEntity.IsNull()) {
                continue;
            }
            res.SetQueryHash(FnvHash<int64_t>(row["query"].AsString()));
            res.SetClusterId(row["ClusterID"].AsInt64());
            res.SetQueryText(row["query"].AsString());
            output->AddRow(res);
        }
    }
};
REGISTER_MAPPER(THashSearchshareMapper)

struct THashSpikesMapper:
    public NYT::IMapper<NYT::TTableReader<NYT::TNode>, NYT::TTableWriter<TQueryToCluster>> {
    void Do(TReader *input, TWriter *output) override {
        TQueryToCluster res;
        for (; input->IsValid(); input->Next()) {
            const auto &row = input->GetRow();
            res.SetQueryHash(FnvHash<int64_t>(row["query"].AsString()));
            res.SetClusterId(FnvHash<int64_t>(row["cluster_id"].AsString()));
            res.SetQueryText(row["query"].AsString());
            output->AddRow(res);
        }
    }
};
REGISTER_MAPPER(THashSpikesMapper)

int TaskApplyHashToClusterTables(int, const char **) {
    const auto& cfg = TConfig::CInstance();

    auto client = NYT::CreateClient(cfg.MR_SERVER_HOST);

    auto tx = client->StartTransaction();

    NComputeGraph::TJobRunner runner;

    auto prevSearchshareID = runner.AddJob([&]() {
        TMapCmd<THashSearchshareMapper>(tx)
            .Input(TTable<NYT::TNode>(tx, cfg.TABLE_SEARCHSHARE_QUERY_TO_CLUSTER))
            .Output(TTable<TQueryToCluster>(tx, cfg.TABLE_SEARCHSHARE_QUERY_TO_CLUSTER_HASHED))
            .Do();
        tx->Remove(cfg.TABLE_SEARCHSHARE_QUERY_TO_CLUSTER);
    });

    // auto prevSpikesID = runner.AddJob([&]() {
    //     TMapCmd<THashSpikesMapper>(tx)
    //         .Input(TTable<NYT::TNode>(tx, cfg.TABLE_SPIKES_QUERY_TO_CLUSTER))
    //         .Output(TTable<TQueryToCluster>(tx, cfg.TABLE_SPIKES_QUERY_TO_CLUSTER_HASHED))
    //         .Do();
    // });

    runner.AddJob([&]() {
        TSortCmd<TKeyHash>(tx)
            .Input<TQueryToCluster>(cfg.TABLE_SEARCHSHARE_QUERY_TO_CLUSTER_HASHED)
            .Output<TQueryToCluster>(cfg.TABLE_SEARCHSHARE_QUERY_TO_CLUSTER_HASHED)
            .By({"QueryHash"})
            .Do();
        },
        {prevSearchshareID}
    );

    // runner.AddJob([&]() {
    //     TSortCmd<TKeyHash>(tx)
    //         .Input<TQueryToCluster>(cfg.TABLE_SPIKES_QUERY_TO_CLUSTER_HASHED)
    //         .Output<TQueryToCluster>(cfg.TABLE_SPIKES_QUERY_TO_CLUSTER_HASHED)
    //         .By({"QueryHash"})
    //         .Do();
    //     },
    //     {prevSpikesID}
    // );

    runner.Run();

    tx->Commit();

    return 0;
}

} //namespace NNiche2
} //namespace NWebmaster
