#include "clickhouse.h"

#include <maps/libs/log8/include/log8.h>
#include <maps/wikimap/mapspro/services/mrc/libs/clickhouse/include/column.h>
#include <maps/wikimap/mapspro/services/mrc/libs/clickhouse/include/table.h>

namespace maps::mrc::user_activity_stat::clickhouse {

namespace {

const TString USER_ACTIVITY_TBL = "user_activity";
const TString USER_COL = "user";
const TString DATE_COL = "date";
const TString PUBLISHED_COL = "published";

struct UserActivityTable
    : maps::mrc::clickhouse::Table<uint64_t, uint64_t, uint64_t> {
    UserActivityTable(TString tableName)
        : Table(std::move(tableName),
                std::make_tuple(USER_COL, DATE_COL, PUBLISHED_COL))
    {
    }
};

auto forEachWriteHost = [](const common::ClickHouseConfig& config, auto fun) {
    NClickHouse::TClientOptions options;
    options.SetDefaultDatabase(TString(config.database()))
        .SetUser(TString(config.user()))
        .SetPassword(TString(config.password()));
    for (const auto& host : config.writeHosts()) {
        NClickHouse::TClient client(options.SetHost(TString(host)));
        fun(client);
    }
};

template <class ClickHouseTable>
void flush(ClickHouseTable& table, const common::ClickHouseConfig& config)
{
    NClickHouse::TBlock block;
    table.addToBlock(block);
    forEachWriteHost(config,
                     [&](auto& client) { client.Insert(table.name(), block); });
    table.clear();
}

}  // namespace

void upload(const TUserActivity& userActivity,
            const common::ClickHouseConfig& config)
{
    UserActivityTable table{USER_ACTIVITY_TBL};
    forEachWriteHost(config, [&](auto& client) { table.create(client); });
    size_t rows = 0;

    for (const auto& [user, activity] : userActivity) {
        for (const auto& [day, counter] : activity) {
            auto ms = static_cast<uint64_t>(
                std::chrono::duration_cast<std::chrono::milliseconds>(
                    day.time_since_epoch())
                    .count());

            table.addRow(std::make_tuple(user, ms, counter));
            if ((++rows % BATCH_SIZE) == 0) {
                flush(table, config);
                INFO() << "clickhouse rows: " << rows;
            }
        }
    }
    if ((rows % BATCH_SIZE) != 0) {
        flush(table, config);
        INFO() << "clickhouse rows: " << rows;
    }
}

}  // namespace maps::mrc::user_activity_stat::clickhouse
