#include <maps/wikimap/ugc/backoffice/src/gdpr/lib/process_takeouts.h>

#include <maps/wikimap/ugc/backoffice/src/gdpr/lib/options.h>
#include <maps/wikimap/ugc/backoffice/src/lib/globals.h>
#include <maps/wikimap/ugc/libs/common/locks.h>

#include <maps/wikimap/mapspro/libs/tasks/include/runner.h>
#include <maps/wikimap/mapspro/libs/tasks/include/yandex/maps/wiki/tasks/status_writer.h>

#include <maps/libs/common/include/exception.h>
#include <maps/libs/common/include/its_detach.h>
#include <maps/libs/pgpool/include/pgpool3.h>
#include <maps/libs/pgpool3utils/include/yandex/maps/pgpool3utils/pg_advisory_mutex.h>
#include <maps/libs/log8/include/log8.h>

namespace ugc = maps::wiki::ugc;
namespace backoffice = maps::wiki::ugc::backoffice;

namespace {

const std::string& CONFIG_PATH = "/etc/yandex/maps/ugc_backoffice/ugc_backoffice.conf";

std::unique_ptr<backoffice::Globals> g_globals;

backoffice::Globals& globals()
{
    REQUIRE(g_globals, "Globals are not initialized");
    return *g_globals;
}

} // namespace

namespace maps::wiki::ugc::backoffice::gdpr {

void run(
    const IDbPools& pools,
    maps::wiki::tasks::StatusWriter& statusWriter,
    bool dryRun)
try {
    statusWriter.reset();
    maps::pgp3utils::PgAdvisoryXactMutex locker(pools[0], locks::GDPR_WORKER_DBMUTEXID);
    if (!locker.try_lock()) {
        INFO() << "Database is already locked. Continue to sleep";
        return;
    }
    INFO() << "Running gdpr worker";

    processTakeouts(pools, dryRun);

    INFO() << "Gdpr worker is done";
    statusWriter.flush();
} catch (const maps::Exception& e) {
    ERROR() << "Caught exception while processing gdpr requests: " << e;
    statusWriter.err(e.what());
    statusWriter.flush();
} catch (const std::exception& e) {
    ERROR() << "Caught exception while processing gdpr requests: " << e.what();
    statusWriter.err(e.what());
    statusWriter.flush();
}

} // namespace maps::wiki::ugc::backoffice::gdpr

int main(int argc, char* argv[])
try {
    if (maps::isHostDetached()) {
        INFO() << "Host is detached, do nothing";
        return EXIT_SUCCESS;
    }
    auto options = backoffice::gdpr::parseOptions(argc, argv, CONFIG_PATH);

    const auto config = maps::json::Value::fromFile(options.confPath);

    g_globals = backoffice::Globals::create(options.confPath, options.dryRun);

    maps::wiki::tasks::StatusWriter statusWriter(options.statusPath);
    INFO() << "UGC GDPR worker is running ...";
    maps::wiki::tasks::Runner().run(
        [&]
        {
            backoffice::gdpr::run(
                globals().pools,
                statusWriter,
                options.dryRun);
        },
        std::chrono::seconds(options.delay)
    );

    g_globals.reset();

    INFO() << "UGC GDPR worker is done";
    return EXIT_SUCCESS;
} catch (const maps::Exception& e) {
    ERROR() << "UGC GDPR worker failed: " << e;
    return EXIT_FAILURE;
} catch (const std::exception& e) {
    ERROR() << "UGC GDPR worker failed: " << e.what();
    return EXIT_FAILURE;
}
