#include <maps/libs/chrono/include/days.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/services/mrc/eye/lib/import_yt_panorama/include/yt_panorama_importer.h>
#include <maps/wikimap/mapspro/services/mrc/libs/common/include/pg_locks.h>
#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>

#include <util/generic/yexception.h>

#include <chrono>
#include <thread>

namespace common = maps::mrc::common;
namespace eye = 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.file("mrc-config")
                             .help("path to mrc config");

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

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

    auto timeout = parser.num("timeout").help("5 minutes by default")
                                        .defaultValue(5);

    auto commit = parser.flag("commit")
                      .help("If set to false don't commit anything to MRC DB (aka dry run)")
                      .defaultValue(false);

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

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

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

    INFO() << "Panorama import process has started";

    do {
        bool sleep = true;
        try {
            // WARN: Don't move importer instance to an outer scope because
            //       the DB is locked until it is alive.
            eye::YtPanoramaImporter importer{
                config, config.externals().yt().makeClient(), commit};

            if (importer.lockDB()) {
                sleep = !importer.import();
            } else {
                WARN() << "Another job is running!";
            }
        } catch (const std::exception& e) {
            WARN() << e.what();
        }

        if (sleep) {
            INFO() << "Sleep for timeout " << timeout << " min";
            std::this_thread::sleep_for(std::chrono::minutes(timeout));
        }
    } while(loop);

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

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

    return EXIT_FAILURE;
} catch (const std::exception& e) {
    FATAL() << "Panorama import failed: " << e.what();
    return EXIT_FAILURE;
} catch (...) {
    FATAL() << "Panorama import failed with an unknown error";

    return EXIT_FAILURE;
}
