#include <library/cpp/testing/unittest/registar.h>
#include <maps/wikimap/mapspro/services/social/src/libs/feedback-actions/find_nearby.h>
#include <maps/wikimap/mapspro/libs/social/tests/helpers/fb_task_creator.h>
#include <maps/wikimap/mapspro/services/social/src/libs/test_helpers/helpers.h>

namespace maps::wiki::socialsrv::tests {

namespace sf = social::feedback;
using sf::tests::FbTaskCreator;

using namespace maps::wiki::socialsrv::serialize;

namespace {

const social::TUid USER_ID = 12;
const std::string SOURCE = "toloka-pedestrian-onfoot";

void createEntrance(
    pqxx::transaction_base& txn,
    social::TId id,
    const geolib3::Point2& position,
    const std::string& entranceTypeValue)
{
    auto commitId = id;
    std::stringstream query;
    query <<
        "SET search_path=vrevisions_trunk, public; "
        "INSERT INTO vrevisions_trunk.objects_p"
        " (id, commit_id, the_geom, domain_attrs) VALUES (" <<
            id << ", " << commitId << ","
            " ST_SetSRID(ST_Point(" << position.x() << "," << position.y() << "), 3395),"
            " hstore(array['cat:poi_entrance', '1'";
    if (!entranceTypeValue.empty()) {
        query << ", 'poi_entrance:type', " << txn.quote(entranceTypeValue);
    }
    query << "])"
        << ")";
    txn.exec(query);
}

TaskForUI createTaskForUI(pqxx::transaction_base& txn)
{
    auto task = FbTaskCreator(txn, sf::TaskState::Opened)
        .type(sf::Type::Entrance)
        .source(SOURCE)
        .position(geolib3::Point2(0, 0))
        .create();

    return TaskForUI(
        std::move(task),
        sf::History{},
        SubstitutionStrategy::None,
        {},
        {},
        USER_ID
    );
}

} // namespace

Y_UNIT_TEST_SUITE(find_nearby_tests) {

Y_UNIT_TEST_F(test, DbFixture) {
    // create feedback
    auto makeTaskForUI = [&] {
        auto writeContext = dbPools().writeContext();
        auto taskForUi = createTaskForUI(writeContext.socialTxn());
        writeContext.commit();
        return taskForUi;
    };

    auto taskForUi = makeTaskForUI();
    UNIT_ASSERT_VALUES_EQUAL(taskForUi.source(), SOURCE);
    UNIT_ASSERT(!taskForUi.objectId());

    findNearbyObject(dbPools(), taskForUi);
    UNIT_ASSERT(!taskForUi.objectId());

    auto makeEntrance = [&](auto id, const auto& position, const std::string& entranceTypeValue = {}) {
        auto writeContext = dbPools().writeContext();
        auto& txn = writeContext.coreTxn(); // hack for view-trunk write transaction
        createEntrance(txn, id, position, entranceTypeValue);
        writeContext.commit();
    };

    makeEntrance(100, geolib3::Point2(10, 10)); // builing entrance
    findNearbyObject(dbPools(), taskForUi);
    UNIT_ASSERT(!taskForUi.nearbyObjectId()); // so far

    makeEntrance(101, geolib3::Point2(3, 3), "service");
    findNearbyObject(dbPools(), taskForUi);
    UNIT_ASSERT(!taskForUi.nearbyObjectId()); // no building

    makeEntrance(102, geolib3::Point2(4, 4), "business");
    findNearbyObject(dbPools(), taskForUi);
    UNIT_ASSERT(!taskForUi.nearbyObjectId()); // no building

    makeEntrance(103, geolib3::Point2(5, 5)); // building entrance
    findNearbyObject(dbPools(), taskForUi);
    UNIT_ASSERT(taskForUi.nearbyObjectId().has_value());
    UNIT_ASSERT_VALUES_EQUAL(taskForUi.nearbyObjectId().value(), 103);
}

} // Y_UNIT_TEST_SUITE(find_nearby_tests)

} // namespace maps::wiki::socialsrv::tests
