#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/libs/mongo/include/init.h>
#include <maps/tools/grinder/worker/include/api.h>
#include <maps/wikimap/mapspro/services/mrc/long_tasks/async_takeout_data_erasure/lib/utility.h>
#include <util/generic/yexception.h>

int main(int argc, char* argv[])
try {
    maps::cmdline::Parser parser;
    auto configPath = parser.string("config").help("path to configuration");
    auto secretVersion = parser.string("secret").help(
        "version for secrets from yav.yandex-team.ru");
    auto syslogTag = parser.string("syslog-tag")
                         .help("redirect log output to syslog with given tag");
    auto grinderConfigPath = parser.string("grinder-config")
                                 .help("path to grinder configuration file");
    parser.parse(argc, argv);

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

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

    maps::mongo::init();

    maps::grinder::worker::Options workerOpts;
    if (grinderConfigPath.defined()) {
        workerOpts.setConfigLocation(grinderConfigPath);
    }
    workerOpts
        .on(maps::mrc::takeout_data_erasure::GRINDER_WORKER_TYPE,
            [&config](const maps::grinder::worker::Task& task) {
                MAPS_LOG_THREAD_PREFIX_APPEND(task.id());
                auto takeoutDataErasureId =
                    task.args()[maps::mrc::takeout_data_erasure::
                                    TAKEOUT_DATA_ERASURE_ID_FIELD]
                        .as<maps::mrc::db::TId>();
                while (true) {
                    try {
                        auto postgres = config.makePoolHolder(
                            maps::mrc::common::LONG_READ_DB_ID,
                            maps::mrc::common::LONG_READ_POOL_ID);
                        maps::mrc::takeout_data_erasure::erasure(
                            postgres.pool(), takeoutDataErasureId);
                        return;
                    }
                    catch (const maps::Exception& e) {
                        ERROR() << e;
                    }
                    catch (const pqxx::failure& e) {
                        ERROR() << e.what();
                    }
                    std::this_thread::sleep_for(std::chrono::seconds(60));
                }
            })
        .setConcurrencyLevel(5);
    maps::grinder::worker::run(workerOpts);
    return EXIT_SUCCESS;
}
catch (const maps::Exception& e) {
    FATAL() << "Worker failed: " << e;
    return EXIT_FAILURE;
}
catch (const std::exception& e) {
    FATAL() << "Worker failed: " << e.what();
    return EXIT_FAILURE;
}
