#include <maps/wikimap/mapspro/services/tasks-ng/lib/db_context.h>
#include <maps/wikimap/mapspro/services/tasks-ng/lib/db_pools.h>
#include <maps/wikimap/mapspro/services/tasks-ng/lib/exception.h>

#include <maps/libs/pgpool/include/pgpool3.h>

namespace maps {
namespace wiki {
namespace tasks_ng {

DbContext::DbContext(AccessMode accessMode)
    : accessMode_(accessMode)
{}

pqxx::transaction_base& DbContext::txnCore()
{
    if (!workCore_) {
        workCore_ = std::make_unique<pgpool3::TransactionHandle>(
            DbPools::get().core().masterWriteableTransaction());
    }
    return *(*workCore_);
}

std::string DbContext::commit(TokenPolicy tokenPolicy)
{
    TASKS_REQUIRE(
        accessMode_ == AccessMode::ReadWrite,
        INTERNAL_ERROR,
        "context in read only mode");

    std::string token;
    if (workCore_) {
        if (tokenPolicy == TokenPolicy::Generate) {
            token = pgpool3::generateToken(txnCore());
        }
        (*workCore_)->commit();
        workCore_.reset();
    }
    return token;
}

DbContext DbContext::toRead(const std::string& token)
{
    DbContext ctx(AccessMode::ReadOnly);
    ctx.workCore_ = std::make_unique<pgpool3::TransactionHandle>(
        DbPools::get().core().slaveTransaction(token));
    return ctx;
}

DbContext DbContext::toWrite()
{
    return DbContext(AccessMode::ReadWrite);
}

} // namespace tasks_ng
} // namespace wiki
} // namespace maps
