#include "published_commits_source.h"

#include "grouper.h"

#include <yandex/maps/wiki/revision/commit.h>
#include <maps/libs/log8/include/log8.h>

#include <memory>

namespace maps::wiki::notifications_dispatcher {

namespace {

const size_t COMMITS_BULK_COUNT = 1000;

}  // namespace

PublishedCommitsSource::PublishedCommitsSource(
        pgpool3::Pool& corePool,
        pgpool3::Pool& socialPool
    )
        : corePool_(corePool)
        , socialPool_(socialPool)
{
    auto txnSocial = socialPool.masterWriteableTransaction();
    social::PublishedCommits publishedCommits{*txnSocial};
    commitIds_ = publishedCommits.getUnprocessedIds(social::commits_handlers::NOTIFICATIONS_DISPATCHER);

    INFO() << "Loaded " << commitIds_.size() << " published commits ids";
}

void PublishedCommitsSource::groupBatches(Grouper& grouper, const GroupInfo& groupInfo) {
    common::applyBatchOp(
        commitIds_,
        COMMITS_BULK_COUNT,
        [&](const auto& batch) {
            auto txnSocial = socialPool_.masterWriteableTransaction();

            auto publishedCommitsData = gatherUsersCommits(*txnSocial, batch);
            grouper.processGroupedNotificationsBatch(*txnSocial, publishedCommitsData, groupInfo);

            social::PublishedCommits publishedCommits{*txnSocial};
            publishedCommits.process(batch, social::commits_handlers::NOTIFICATIONS_DISPATCHER);

            txnSocial->commit();
        }
    );
}

PublishedCommitsData PublishedCommitsSource::gatherUsersCommits(
    pqxx::transaction_base& txnSocial,
    const social::TIds& commitIds
) const {
    auto readCommits = [&] {
        auto txnCore = corePool_.slaveTransaction();
        return revision::Commit::load(
            *txnCore,
            revision::filters::CommitAttr::id().in(commitIds)
        );
    };

    social::ProfileGateway profileGateway{txnSocial};

    return PublishedCommitsData(profileGateway, readCommits());
}

}  // maps::wiki::notifications_dispatcher
