#include <maps/wikimap/mapspro/services/mrc/eye/lib/common/include/txn.h>

#include <library/cpp/testing/common/env.h>
#include <library/cpp/testing/gtest/gtest.h>
#include <maps/libs/local_postgres/include/instance.h>
#include <maps/libs/log8/include/log8.h>

namespace maps::mrc::eye::tests {

const std::string MIGRATIONS_PATH = ArcadiaSourceRoot() \
    + "/maps/wikimap/mapspro/services/mrc/eye/lib/common/tests/migrations";

auto makePool(
        const local_postgres::Database& db,
        const local_postgres::Server& master,
        const local_postgres::Server& slave)
{
    const pgpool3::PoolConfiguration config {
        pgpool3::InstanceId {master.host(), master.port()},
        {
            pgpool3::InstanceId {slave.host(), slave.port()}
        }
    };

    return pgpool3::Pool{
        config,
        db.connectionString(),
        pgpool3::PoolConstants{/*master*/ 1, 3,  /*slave*/ 1, 3}
    };
}

TEST(get_txn, token)
{
    local_postgres::Database masterDb;
    masterDb.applyMigrations(MIGRATIONS_PATH);

    auto& master = *masterDb.server();
    auto slave = master.createSlave();
    pgpool3::Pool pool = makePool(masterDb, master, slave);

    const auto masterId = pool.state().configuration.master();
    const auto slaveId = pool.state().configuration.slaves().front();

    {
        const auto token = getNewToken(pool);

        auto one = getSlaveTxn(pool, token);
        EXPECT_EQ(one.releaseConnection().instance(), slaveId);

        auto two = getSlaveTxn(pool);
        EXPECT_EQ(two.releaseConnection().instance(), slaveId);
    }

    {
        auto masterTxn = getMasterWriteTxn(pool);
        masterTxn->exec("INSERT INTO person(name) VALUES (('Anna'));");
        auto txn = getSlaveTxn(pool, commit(*masterTxn));

        EXPECT_EQ(txn.releaseConnection().instance(), slaveId);
    }

    {
        auto txn = getSlaveTxn(pool, "FFFF/FFFF");
        EXPECT_EQ(txn.releaseConnection().instance(), masterId);
    }
}

} // namespace maps::mrc::eye::tests
