#include <maps/wikimap/mapspro/services/autocart/pipeline/libs/wiki/include/table.h>
#include <maps/wikimap/mapspro/services/autocart/pipeline/libs/assessors/include/assessor.h>
#include <maps/wikimap/mapspro/services/autocart/pipeline/libs/assessors/include/utils.h>

#include <tuple>

namespace maps::wiki::autocart::pipeline {

namespace {

constexpr const char* FIELD_ID = "id";
constexpr const char* FIELD_LOGIN = "login";
constexpr const char* FIELD_COMPANY = "company";

} // namespace

Assessor Assessor::fromYTNode(const NYT::TNode& node) {
    Assessor assessor;
    assessor.id = node[FIELD_ID].AsString();
    assessor.login = node[FIELD_LOGIN].AsString();
    assessor.company = node[FIELD_COMPANY].AsString();
    return assessor;
}

Assessor Assessor::fromWikiTableRow(const WikiTableRow& row) {
    Assessor assessor;
    assessor.id = strip(row.at(FIELD_ID));
    assessor.login = strip(row.at(FIELD_LOGIN));
    assessor.company = strip(row.at(FIELD_COMPANY));
    return assessor;
}

NYT::TNode Assessor::toYTNode() const {
    NYT::TNode node;
    node[FIELD_ID] = TString(id);
    node[FIELD_LOGIN] = TString(login);
    node[FIELD_COMPANY] = TString(company);
    return node;
}

bool Assessor::operator<(const Assessor& that) const {
    return std::tie(id, login, company)
        < std::tie(that.id, that.login, that.company);
}

bool Assessor::operator==(const Assessor& that) const {
    return std::tie(id, login, company)
        == std::tie(that.id, that.login, that.company);
}

std::vector<Assessor> loadAssessorsFromWikiTable(
    const std::string& tableName, const std::string& oauthToken)
{
    WikiTable wikiTable = loadWikiTable(tableName, oauthToken);
    std::vector<Assessor> assessors;
    for (const WikiTableRow& row : wikiTable) {
        Assessor assessor = Assessor::fromWikiTableRow(row);
        if (!assessor.id.empty() &&
            !assessor.login.empty() &&
            !assessor.company.empty())
        {
            assessors.push_back(assessor);
        }
    }
    return assessors;
}

std::map<std::string, std::string> loadLoginByWorkerIdFromWikiTable(
    const std::string& tableName, const std::string& oauthToken)
{
    std::map<std::string, std::string> loginByWorkerId;

    for (auto&& assessor : loadAssessorsFromWikiTable(tableName, oauthToken)) {
        loginByWorkerId[std::move(assessor.id)] = std::move(assessor.login);
    }

    return loginByWorkerId;
}

std::vector<Assessor> loadAssessorsFromYTTable(
    NYT::IClientBasePtr client, const TString& tableName)
{
    NYT::TTableReaderPtr<NYT::TNode> reader
        = client->CreateTableReader<NYT::TNode>(tableName);
    std::vector<Assessor> assessors;
    for (; reader->IsValid(); reader->Next()) {
        const NYT::TNode& row = reader->GetRow();
        assessors.push_back(Assessor::fromYTNode(row));
    }
    return assessors;
}

} // namespace maps::wiki::autocart::pipeline
