#include <maps/wikimap/mapspro/services/mrc/eye/lib/verify_detection_pair_match/include/verify_detection_pair_match.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/common/include/id_stream.h>

#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>

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

#include <chrono>
#include <thread>

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

int main(int argc, const char** argv) try {
    maps::cmdline::Parser parser;

    auto syslog = parser.string("syslog-tag")
            .help("redirect log output to syslog with given tag");

    auto mrcConfigPath = parser.string("mrc-config")
            .help("path to mrc config");

    auto secretVersion = parser.string("secret-version")
            .help("version for secrets from yav.yandex-team.ru");

    auto matchIdsPath = parser.string("match-ids")
            .help("path to match ids file");

    auto loop = parser.flag("loop")
            .help("work in infinite loop");

    auto batchSize = parser.num("batch")
            .defaultValue(1000)
            .help("match batch size (default 1000)");

    auto commit = parser.flag("commit")
            .help("commit results");

    auto lockFree = parser.flag("lock-free")
            .help("lock free import (may be dangerous)");

    auto timeout = parser.num("timeout")
            .help("wait for db update in minutes (default 5)")
            .defaultValue(5);

    parser.parse(argc, const_cast<char**>(argv));

    if (syslog.defined()) {
        log8::setBackend(log8::toSyslog(syslog));
    }

    const auto config =
        maps::mrc::common::templateConfigFromCmdPath(secretVersion,
                                                     mrcConfigPath);

    wiki::common::PoolHolder poolHolder = config.makePoolHolder();
    FrameUrlResolver frameUrlResolver(
        config.externals().mrcBrowserUrl(),
        config.externals().mrcBrowserProUrl());

    DetectionPairMatchVerifierConfig workerConfig;
    workerConfig.mrc.pool = &poolHolder.pool();
    workerConfig.mrc.commit = commit;
    workerConfig.mrc.lockFree = lockFree;
    workerConfig.frameUrlResolver = &frameUrlResolver;

    DetectionPairMatchVerifier worker(workerConfig);

    if (not loop) {
        if (matchIdsPath.defined()) {
            for (IdStream idStream(matchIdsPath); idStream.valid(); ) {
                worker.processBatch(idStream.readBatch(batchSize));
            }
        } else {
            WARN() << "No recognition ids!";
        }

        return EXIT_SUCCESS;
    }

    INFO() << "Infinite loop mode...";
    if (matchIdsPath.defined()) {
        WARN() << "Ignore match ids '" << matchIdsPath << "'";
    }

    worker.runInLoopMode(batchSize, std::chrono::minutes(timeout));

    return EXIT_SUCCESS;
} catch (const maps::Exception& e) {
    FATAL() << e;
    return EXIT_FAILURE;
} catch (const yexception& e) {
    FATAL() << e.what();

    if (e.BackTrace()) {
        FATAL() << e.BackTrace()->PrintToString();
    }

    return EXIT_FAILURE;
} catch (const std::exception& e) {
    FATAL() << e.what();
    return EXIT_FAILURE;
} catch (...) {
    FATAL() << "Unknown error!";
    return EXIT_FAILURE;
}
