#include <maps/wikimap/mapspro/services/mrc/eye/lib/import_mrc/include/metadata.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/monitoring/include/check.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/monitoring/include/common.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/libs/db/include/feature_gateway.h>

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/log8/include/log8.h>

#include <maps/libs/common/include/exception.h>

#include <iostream>

using namespace maps::mrc;
using namespace maps::mrc::eye;

namespace {

juggler::Message checkImportQueueSize(MetadataManager& metadata, db::FeatureTransactionGateway& gateway)
{
    static constexpr int64_t WARN_QUEUE_SIZE = 300000;
    static constexpr int64_t ERROR_QUEUE_SIZE = 1000000;

    const int64_t size = gateway.count(
        db::table::FeatureTransaction::transactionId >= metadata.getTxnId()
    );

    const std::string message = std::to_string(size) + " features in queue";

    if (size > ERROR_QUEUE_SIZE) {
        return juggler::error(message);
    } else if (size > WARN_QUEUE_SIZE) {
        return juggler::warn(message);
    } else {
        return juggler::ok(message);
    }
}

} // namespace

int main(int argc, char** argv) try {
    maps::log8::setLevel(maps::log8::Level::ERROR);

    auto config = maps::mrc::common::templateConfig();
    auto pool = config.makePoolHolder();
    auto txn = pool.pool().slaveTransaction();

    auto metadata = eye::importMrcMetadata(*txn);
    db::FeatureTransactionGateway gateway(*txn);

    const MonitoringCheck checkQueue = std::bind(
        checkImportQueueSize,
        std::ref(metadata),
        std::ref(gateway)
    );

    const MonitoringCheckByName checkByName {
        {"queue-size", checkQueue},
    };

    maps::cmdline::Parser parser;

    auto name = parser.string("check")
        .help("checks: " + collectNameList(checkByName))
        .required();

    parser.parse(argc, argv);

    REQUIRE(checkByName.count(name), "Unknown check " << name);
    std::cout << checkByName.at(name)() << std::endl;

    return EXIT_SUCCESS;
} catch (const std::exception& e) {
    std::cout << juggler::error(e.what()) << std::endl;
    return EXIT_FAILURE;
} catch (...) {
    std::cout << juggler::error("unknown exception") << std::endl;
    return EXIT_FAILURE;
}
