#include <maps/libs/chrono/include/time_point.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/libs/sql_chemistry/include/batch_load.h>
#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/feature_gateway.h>

namespace {

const auto WARN_PENDING_HOURS = std::chrono::hours{24};
const auto ERROR_PENDING_HOURS = std::chrono::hours{48};

std::optional<maps::chrono::TimePoint> loadMinUploadTime()
{
    auto config = maps::mrc::common::templateConfig();
    auto postgres = config.makePoolHolder(maps::mrc::common::LONG_READ_DB_ID,
                                          maps::mrc::common::LONG_READ_POOL_ID);
    auto result = std::optional<maps::chrono::TimePoint>{};
    auto batch = maps::sql_chemistry::BatchLoad<maps::mrc::db::table::Feature>{
        100'000u, maps::mrc::db::table::Feature::processedAt.isNull()};
    while (batch.next(*postgres.pool().slaveTransaction())) {
        std::for_each(batch.begin(), batch.end(), [&](const auto& feature) {
            if (!feature.hasQuality() && !feature.hasRoadProbability() &&
                !feature.hasForbiddenProbability()) {
                if (result) {
                    result = std::min(*result, feature.uploadedAt());
                }
                else {
                    result = feature.uploadedAt();
                }
            }
        });
    }
    return result;
}

}  // namespace

int main()
try {
    maps::log8::setLevel(maps::log8::Level::FATAL);
    auto optMinUploadTime = loadMinUploadTime();
    if (!optMinUploadTime.has_value()) {
        std::cout << "0;OK: no pending featues exist" << std::endl;
    }
    else {
        const auto lag = std::chrono::duration_cast<std::chrono::hours>(
            maps::chrono::TimePoint::clock::now() - optMinUploadTime.value());
        if (lag > ERROR_PENDING_HOURS) {
            std::cout << "2;Error: ";
        }
        else if (lag > WARN_PENDING_HOURS) {
            std::cout << "1;Warning: ";
        }
        else {
            std::cout << "0;OK: ";
        }
        std::cout << "the oldest pending feature is " << lag.count()
                  << " hours old" << std::endl;
    }
    return EXIT_SUCCESS;
}
catch (const std::exception& e) {
    std::cout << "2;Error: " << e.what() << std::endl;
    return EXIT_SUCCESS;
}
