#include <maps/wikimap/mapspro/services/mrc/long_tasks/assignment_object_feedback_tasks_emitter/emitter/emitter.h>
#include <maps/wikimap/mapspro/services/mrc/long_tasks/assignment_object_feedback_tasks_emitter/emitter/magic_strings.h>

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/libs/chrono/include/time_point.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/metadata_gateway.h>
#include <maps/libs/common/include/exception.h>
#include <maps/libs/common/include/make_batches.h>
#include <maps/libs/log8/include/log8.h>

namespace {

constexpr std::size_t BATCH_SIZE = 1000;

void saveMetadata(maps::mrc::common::Config& cfg, size_t postedFeedbackCount)
{
    namespace social = maps::mrc::social;
    namespace chrono = maps::chrono;
    auto poolHolder = cfg.makePoolHolder(maps::mrc::common::LONG_READ_DB_ID,
                                         maps::mrc::common::LONG_READ_POOL_ID);
    auto txn = poolHolder.pool().masterWriteableTransaction();
    auto gtw = maps::mrc::db::MetadataGateway{*txn};
    gtw.upsertByKey(
        social::metadataKey(social::TIMESTAMP_KEY),
        chrono::formatSqlDateTime(chrono::TimePoint::clock::now()));
    gtw.upsertByKey(social::metadataKey(social::POSTED_FEEDBACK_COUNT_KEY),
                    postedFeedbackCount);
    txn->commit();
}

} // namespace

int main(int argc, char* argv[]) try {
    using namespace maps::mrc::social;

    maps::cmdline::Parser parser("A tool that posts objects found by users "
                                 "of MRC app as feedback tasks to the map "
                                 "editor");
    auto syslog = parser.string("syslog-tag")
                      .help("redirect log output to syslog with given tag");
    auto configPath = parser.string("config").help("path to configuration");
    parser.parse(argc, argv);

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

    auto cfg = maps::mrc::common::templateConfigFromCmdPath(configPath);

    AssignmentObjectFeedbackTasksEmitter emitter(cfg);
    emitter.initTvmClient();

    std::size_t postedFeedbackTasks = 0;

    auto unpostedIds = emitter.loadUnpostedAssignmentObjectIds();
    for (const auto& batch : maps::common::makeBatches(unpostedIds, BATCH_SIZE)) {
        auto assignmentObjects = emitter.loadPublishableAssignmentObjects(
            {batch.begin(), batch.end()});
        emitter.postFeedbackTasks(assignmentObjects);
        postedFeedbackTasks += assignmentObjects.size();
    }

    saveMetadata(cfg, postedFeedbackTasks);
    INFO() << "Finished, posted feedback tasks: " << postedFeedbackTasks
           << ", pending: " << unpostedIds.size() - postedFeedbackTasks;
} catch (const maps::mrc::social::AnotherProcessIsRunning&) {
    INFO() << "Parallel process is ongoing";
    return EXIT_SUCCESS;
} catch (const maps::Exception& e) {
    ERROR() << e;
    return EXIT_FAILURE;
} catch (const std::exception& e) {
    ERROR() << e.what();
    return EXIT_FAILURE;
}
