#include <mapreduce/yt/interface/client.h>
#include <maps/libs/chrono/include/time_point.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/libs/pgpool/include/pgpool3.h>
#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/metadata_gateway.h>
#include <maps/wikimap/mapspro/services/mrc/long_tasks/import_taxi/lib/common.h>
#include <yandex/maps/wiki/common/pgpool3_helpers.h>

#include <cstdint>

using namespace maps::mrc::import_taxi;

namespace {

// Table lag is 24 h
constexpr std::chrono::hours WARN_LAG{48};
constexpr std::chrono::hours ERROR_LAG{96};
const std::string CREATED_AT = "created_at";

}  // namespace

int main()
try {
    maps::log8::setLevel(maps::log8::Level::FATAL);
    const auto now = maps::chrono::TimePoint::clock::now();

    auto cfg = maps::mrc::common::templateConfig();
    auto pool = cfg.makePoolHolder(maps::mrc::common::LONG_READ_DB_ID,
                                   maps::mrc::common::LONG_READ_POOL_ID);
    auto metadata = getMetadata(pool.pool());


    const auto runLag = std::chrono::duration_cast<std::chrono::hours>(
        now - metadata.lastRunTimestamp);
    auto processingLag = std::chrono::hours{0};

    const auto& importCfg = cfg.taxiImportConfig();
    auto ytClient = NYT::CreateClient(
        TString(importCfg.ytCluster()),
        NYT::TCreateClientOptions().Token(TString(importCfg.ytToken()))
    );

    auto key = metadata.maxProcessedEventId + 1;
    auto path = NYT::TRichYPath(importCfg.ytEventsPath() + "events")
        .AddRange(NYT::TReadRange::FromKeys(key, key + 1))
        .Columns({CREATED_AT});
    auto reader = ytClient->CreateTableReader<NYT::TNode>(path);
    if (reader->IsValid()) {
        const auto& row = reader->GetRow();
        processingLag = std::chrono::duration_cast<std::chrono::hours>(
            now - toTimePoint(row[CREATED_AT].AsDouble()));
    }

    if (runLag > ERROR_LAG || processingLag > ERROR_LAG) {
        std::cout << "2;Error: ";
    } else if (runLag > WARN_LAG || processingLag > WARN_LAG) {
        std::cout << "1;Warning: ";
    } else {
        std::cout << "0;Ok: ";
    }
    std::cout << "taxi importer ran " << runLag.count() << " hours ago, "
              << "processing lag is " << processingLag.count() << " hours";

    return EXIT_SUCCESS;
}
catch (const std::exception& e) {
    std::cout << "2;Error: " << e.what() << std::endl;
    return EXIT_SUCCESS;
}
