#include <maps/wikimap/mapspro/services/tasks_realtime/src/mrc_pedestrian_tasks_generator/lib/tasks_generator.h>

#include <yandex/maps/wiki/common/default_config.h>
#include <yandex/maps/wiki/common/extended_xml_doc.h>
#include <yandex/maps/wiki/common/pgpool3_helpers.h>
#include <yandex/maps/wiki/common/secrets.h>

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/common/include/exception.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/wikimap/mapspro/libs/tasks/include/runner.h>

#include <chrono>
#include <exception>
#include <memory>
#include <string>
#include <thread>

namespace mp = maps::wiki::tasks::mrc_pedestrian;

namespace {

const std::string DB_ID = "long-read";
const std::string POOL_ID = "long-read";

const std::chrono::seconds WORKER_SLEEP_PERIOD{30};

} // anonymous namespace

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

    auto servicesConfig = parser.file("config").help(
        "path to services configuration file");
    auto tvmServiceTicket = parser.string("tvm-service-ticket").help(
        "TVM service ticket to use in requests");
    auto syslogTag = parser.string("syslog-tag").help(
        "redirect log output to syslog with given tag");

    parser.parse(argc, argv);

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

    auto configPtr = servicesConfig.defined()
        ? std::make_unique<maps::wiki::common::ExtendedXmlDoc>(servicesConfig)
        : maps::wiki::common::loadDefaultConfig();

    maps::wiki::common::PoolHolder poolHolder(*configPtr, DB_ID, POOL_ID);

    auto ugcBackofficeHost = configPtr->get<std::string>(
        "/config/common/ugc-backoffice/base-url");

    std::unique_ptr<mp::ServiceTicketProvider> serviceTicketProvider;
    if (tvmServiceTicket.defined()) {
        serviceTicketProvider = std::make_unique<mp::FixedServiceTicketProvider>(tvmServiceTicket);
    } else {
        serviceTicketProvider = std::make_unique<mp::TvmtoolServiceTicketProvider>();
    }

    mp::TasksGenerator generator(
        poolHolder.pool(),
        mp::UgcBackofficeClient(std::move(ugcBackofficeHost), std::move(serviceTicketProvider)));

    maps::wiki::tasks::Runner runner;
    runner.run([&]{
        size_t commitsConsumed = 0;
        do {
            commitsConsumed = 0;
            try {
                commitsConsumed = generator.consumeNewCommits();
            } catch (const maps::Exception& ex) {
                ERROR() << "Consume failed: " << ex;
            } catch (const std::exception& ex) {
                ERROR() << "Consume failed: " << ex.what();
            }
        } while (commitsConsumed >= mp::PUBSUB_CONSUMER_BATCH_SIZE);
        INFO() << "All commits processed, sleeping...";
    }, WORKER_SLEEP_PERIOD);

    return EXIT_SUCCESS;
} catch (const maps::Exception& ex) {
    FATAL() << "Worker failed: " << ex;
    return EXIT_FAILURE;
} catch (const std::exception& ex) {
    FATAL() << "Worker failed: " << ex.what();
    return EXIT_FAILURE;
}
