#include "common.h"
#include "fixture.h"

#include <maps/libs/concurrent/include/scoped_guard.h>
#include <maps/libs/http/include/test_utils.h>
#include <maps/libs/img/include/algorithm.h>
#include <maps/libs/img/include/raster.h>
#include <maps/libs/json/include/value.h>
#include <maps/libs/log8/include/log8.h>
#include <maps/wikimap/mapspro/services/mrc/browser/lib/configuration.h>
#include <maps/wikimap/mapspro/services/mrc/browser/lib/feature_author.h>

#include <maps/libs/common/include/exception.h>
#include <maps/libs/common/include/file_utils.h>
#include <yandex/maps/mrc/unittest/utils.h>
#include <maps/infra/yacare/include/yacare.h>
#include <maps/infra/yacare/include/test_utils.h>


#include <library/cpp/testing/gmock_in_unittest/gmock.h>
#include <library/cpp/testing/unittest/env.h>
#include <library/cpp/testing/unittest/registar.h>

#include <filesystem>
#include <sstream>

using namespace testing;

namespace maps::mrc::browser::tests {

namespace {

cv::Mat expectedTestImage()
{
    static auto blob
        = maps::common::readFileToString(SRC_("expected/fisheye.jpeg"));
    return mrc::common::decodeImage(blob);
}

cv::Mat expectedTestImageBlurred()
{
    static auto blob
        = maps::common::readFileToString(SRC_("expected/fisheye.blurred.jpeg"));
    return mrc::common::decodeImage(blob);
}

db::TIds collectIdsFromJson(const json::Value& array)
{
    db::TIds ids;
    for (auto item : array) {
        ids.push_back(
            std::stoll(item["properties"]["id"].as<std::string>())
        );
    }
    return ids;
};

} // namespace

Y_UNIT_TEST_SUITE(feature_api_fb_should) {

Y_UNIT_TEST(get_tiles)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET,
            http::URL("http://localhost/tiles")
                .setParams("x=79222&y=41104&z=17&l=mrcss"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    EXPECT_EQ(
        img::RasterImage::fromPngBlob(common::toBytes(resp.body)),
        img::RasterImage::fromPngFile(SRC_("expected/tiles_mrcss_79222_41104_17.png"))
    );
}

Y_UNIT_TEST(get_feature_full_response)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET, http::URL("http://localhost/feature/1/image"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    const cv::Mat image = mrc::common::decodeImage(resp.body);
    EXPECT_TRUE(unittest::areImagesEq(image, expectedTestImage()));
}

Y_UNIT_TEST(get_feature_thumbnail)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET, http::URL("http://localhost/feature/1/thumbnail"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    EXPECT_EQ(resp.body.size(), 16562u);
}

Y_UNIT_TEST(get_feature_image_with_blurred_privacy)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET, http::URL("http://localhost/feature/2/image"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    const cv::Mat image = mrc::common::decodeImage(resp.body);
    EXPECT_TRUE(unittest::areImagesEq(image, expectedTestImageBlurred()));
}


Y_UNIT_TEST(get_features_hotspot)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/hotspot")
                .setParams("x=79222&y=41104&z=17"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    auto json = json::Value::fromString(resp.body);
    maps::common::writeFile("reponse.json", resp.body);
    EXPECT_EQ(json["data"]["features"].size(), 8u);
}

Y_UNIT_TEST(get_features_hotspot_full_response_for_walk_feature)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/hotspot")
                .setParams("x=652445&y=325766&z=20"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    auto json = json::Value::fromString(resp.body);
    EXPECT_EQ(json["data"]["features"].size(), 2u);
    for (const auto& feature : json["data"]["features"]) {
        EXPECT_TRUE(
                feature["properties"]["properties"].hasField("targetGeometry"));
    }
}

Y_UNIT_TEST(get_features_path)
{
    auto fixture = FixtureFb{};
    struct {
        db::TId featureId;
        size_t before;
        size_t after;
        db::TIds expect;
    } tests[] = {
        {.featureId = 4, .before = 100, .after = 100, .expect = {2, 4, 6, 8}},
        {.featureId = 2, .before = 100, .after = 1, .expect = {2, 4}},
        {.featureId = 8, .before = 1, .after = 100, .expect = {6, 8}},
    };
    for (auto& [featureId, before, after, expect] : tests) {
        auto rq = http::MockRequest(
            http::GET,
            http::URL("http://localhost/features/" + std::to_string(featureId) +
                      "/path")
                .addParam("before_limit", std::to_string(before))
                .addParam("after_limit", std::to_string(after)));
        auto resp = yacare::performTestRequest(rq);
        EXPECT_EQ(resp.status, 200);

        auto json = json::Value::fromString(resp.body);
        auto features = json["data"]["features"];
        EXPECT_EQ(features.size(), expect.size());
        for (size_t i = 0; i < features.size(); ++i) {
            EXPECT_EQ(features[i]["properties"]["id"].toString(),
                      std::to_string(expect[i]));
        }
    }
}

Y_UNIT_TEST(get_features_coverage)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/coverage")
                .addParam("bbox", "43.998,56.3218~44.0,56.322"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    auto json = json::Value::fromString(resp.body);
    EXPECT_EQ(json["coverage"].as<bool>(), true);
}

Y_UNIT_TEST(get_features_stamp)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/stamp.xml"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
}

Y_UNIT_TEST(get_features_directions)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET,
                         http::URL("http://localhost/features/"
                                   "directions?ll=37.569599,55.791591")
                             .addParam("dir", 190));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
}


} // Y_UNIT_TEST_SUITE_F

Y_UNIT_TEST_SUITE(feature_api_fb_author_should) {

const std::string PUBLIC_ID = "123";
const std::string AVATAR_ID = "123/avatar-id";
const std::string LOGIN = "test_login";
const std::string NAME = "test_name";
const std::string UID = "123";

using namespace blackbox_client;

const auto WALK_USER_INFO = [] {
    auto result = auth::UserInfo{};
    result.setDisplayName(auth::DisplayName{
        .publicName = NAME, .name = NAME, .avatarId = AVATAR_ID});
    result.setLogin(LOGIN);
    result.setPublicId(UID);
    result.setUid(UID);
    return result;
}();

std::string makeAvatarUrl(const std::string& avatarId)
{
    return "https://avatars.mds.yandex.net/get-yapic/" + avatarId + "/{size}";
}

bool isExpectedAuthor(const json::Value& author, const UserInfo& expected)
{
    return author["uid"].as<std::string>() == expected.uid()
        && author["login"].as<std::string>() == expected.login()
        && author["name"].as<std::string>() == expected.displayName()->name
        && author["avatarUrl"].as<std::string>() == makeAvatarUrl(*expected.displayName()->avatarId);
}

inline auto makeNiceMockBlackboxClient() {
    return std::make_unique<NiceMock<MockBlackboxClient>>();
}

Y_UNIT_TEST(test_hotspot_request_with_authors)
{
    FixtureFb fixture;
    const std::string SCHEMA_PATH =
        apiResponseSchemaPath("browser/get_hotspots.response.schema.json");
    const std::string RESPONSE_PATH = "hotspot.json";

    http::MockRequest rq(http::GET,
        http::URL("http://localhost/features/hotspot")
            .setParams("x=81555&y=40720&z=17&with_authors=true"));
    rq.headers.emplace(yacare::tests::USER_ID_HEADER, std::to_string(fixture.UID));
    auto resp = yacare::performTestRequest(rq);

    EXPECT_EQ(resp.status, 200);
    maps::common::writeFile(RESPONSE_PATH, resp.body);
    validateJson(RESPONSE_PATH, SCHEMA_PATH);
    auto receivedJson = json::Value::fromString(resp.body);

    EXPECT_EQ(receivedJson["data"]["features"].size(), 2u);
    for (const auto& feature : receivedJson["data"]["features"]) {
        EXPECT_TRUE(isExpectedAuthor(feature["properties"]["properties"]["author"], YANDEX_USER_INFO));
    }
}

Y_UNIT_TEST(test_hotspot_request_walk_features_with_authors)
{
    FixtureFb fixture;

    const std::string SCHEMA_PATH =
        apiResponseSchemaPath("browser/get_hotspots.response.schema.json");
    const std::string RESPONSE_PATH = "hotspot_walks.json";

    Configuration::instance()->swapBlackboxClient(makeNiceMockBlackboxClient());

    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/hotspot")
                .setParams("x=652445&y=325766&z=20")
                .addParam("with_authors", "true"));
    rq.headers.emplace(yacare::tests::USER_ID_HEADER, std::to_string(fixture.UID));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);

    maps::common::writeFile(RESPONSE_PATH, resp.body);
    validateJson(RESPONSE_PATH, SCHEMA_PATH);

    auto json = json::Value::fromString(resp.body);
    EXPECT_EQ(json["data"]["features"].size(), 2u);
    for (const auto& feature : json["data"]["features"]) {
        EXPECT_TRUE(isExpectedAuthor(feature["properties"]["properties"]["author"], /*WALK_USER_INFO*/YANDEX_USER_INFO));
    }
}

Y_UNIT_TEST(test_find_request_with_authors)
{
    FixtureFb fixture;

    const std::string SCHEMA_PATH =
        apiResponseSchemaPath("browser/get_find.response.schema.json");
    const std::string RESPONSE_PATH = "find.json";

    http::MockRequest rq(http::GET,
                         http::URL("http://localhost/features/find")
                             .addParam("ids", "9,10")
                             .addParam("with_authors", "true"));
    rq.headers.emplace(yacare::tests::USER_ID_HEADER,
                       std::to_string(fixture.UID));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);

    maps::common::writeFile(RESPONSE_PATH, resp.body);
    validateJson(RESPONSE_PATH, SCHEMA_PATH);

    auto json = json::Value::fromString(resp.body);
    EXPECT_EQ(json["data"]["features"].size(), 2u);
    for (const auto& feature : json["data"]["features"]) {
        EXPECT_TRUE(isExpectedAuthor(feature["author"], YANDEX_USER_INFO));
    }
}

Y_UNIT_TEST(test_find_request_no_photo)
{
    FixtureFb fixture;

    auto maxId = db::FeatureGateway{*fixture.txnHandle()}
                     .loadIds(orderBy(db::table::Feature::id).desc().limit(1))
                     .front();

    const std::string SCHEMA_PATH =
        apiResponseSchemaPath("browser/get_find.response.schema.json");
    const std::string RESPONSE_PATH = "find.json";

    http::MockRequest rq(http::GET,
                         http::URL("http://localhost/features/find")
                             .addParam("ids", std::to_string(maxId + 1)));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);

    maps::common::writeFile(RESPONSE_PATH, resp.body);
    validateJson(RESPONSE_PATH, SCHEMA_PATH);

    auto json = json::Value::fromString(resp.body);
    EXPECT_EQ(json["data"]["features"].size(), 0u);
}

Y_UNIT_TEST(test_path_request_with_authors)
{
    FixtureFb fixture;

    const std::string SCHEMA_PATH =
        apiResponseSchemaPath("browser/get_path.response.schema.json");
    const std::string RESPONSE_PATH = "path.json";

    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/2/path")
                .addParam("with_authors", "true"));
    rq.headers.emplace(yacare::tests::USER_ID_HEADER, std::to_string(fixture.UID));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);

    maps::common::writeFile(RESPONSE_PATH, resp.body);
    validateJson(RESPONSE_PATH, SCHEMA_PATH);

    auto json = json::Value::fromString(resp.body);

    EXPECT_TRUE(json["data"].hasField("author"));
    EXPECT_TRUE(isExpectedAuthor(json["data"]["author"], YANDEX_USER_INFO));
}

Y_UNIT_TEST(test_similar_request_with_authors)
{
    FixtureFb fixture;

    const std::string SCHEMA_PATH =
        apiResponseSchemaPath("browser/get_similar.response.schema.json");
    const std::string RESPONSE_PATH = "similar.json";

    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/2/similar")
                .addParam("with_authors", "true"));
    rq.headers.emplace(yacare::tests::USER_ID_HEADER, std::to_string(fixture.UID));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);

    maps::common::writeFile(RESPONSE_PATH, resp.body);
    validateJson(RESPONSE_PATH, SCHEMA_PATH);

    auto json = json::Value::fromString(resp.body);

    for (const auto& feature : json["data"]["features"]) {
        EXPECT_TRUE(feature.hasField("author"));
        EXPECT_TRUE(isExpectedAuthor(feature["author"], YANDEX_USER_INFO));
    }
}

Y_UNIT_TEST(test_similar_request_walks_with_authors)
{
    FixtureFb fixture;

    const std::string SCHEMA_PATH =
        apiResponseSchemaPath("browser/get_similar.response.schema.json");
    const std::string RESPONSE_PATH = "similar.json";

    Configuration::instance()->swapBlackboxClient(makeNiceMockBlackboxClient());

    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/9/similar")
                .addParam("with_authors", "true"));
    rq.headers.emplace(yacare::tests::USER_ID_HEADER, std::to_string(fixture.UID));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);

    maps::common::writeFile(RESPONSE_PATH, resp.body);
    validateJson(RESPONSE_PATH, SCHEMA_PATH);

    auto json = json::Value::fromString(resp.body);
    EXPECT_EQ(json["data"]["features"].size(), 2ul);
    for (const auto& feature : json["data"]["features"]) {
        EXPECT_TRUE(feature.hasField("author"));
        const auto& author = feature["author"];
        //const auto& featureId = feature["properties"]["id"].as<std::string>();

        //if (featureId == "9" || featureId == "10") {
        //    EXPECT_TRUE(isExpectedAuthor(author, WALK_USER_INFO));
        //} else {
            EXPECT_TRUE(isExpectedAuthor(author, YANDEX_USER_INFO));
        //}
    }
}

Y_UNIT_TEST(test_near_request_with_authors)
{
    FixtureFb fixture;

    const std::string SCHEMA_PATH =
        apiResponseSchemaPath("browser/get_near.response.schema.json");
    const std::string RESPONSE_PATH = "near.json";

    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/near?ll=43.9992,56.3218")
                .addParam("with_authors", "true"));
    rq.headers.emplace(yacare::tests::USER_ID_HEADER, std::to_string(fixture.UID));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);

    maps::common::writeFile(RESPONSE_PATH, resp.body);
    validateJson(RESPONSE_PATH, SCHEMA_PATH);

    auto json = json::Value::fromString(resp.body);

    for (const auto& feature : json["data"]["features"]) {
        EXPECT_TRUE(feature.hasField("author"));
        EXPECT_TRUE(isExpectedAuthor(feature["author"], YANDEX_USER_INFO));
    }
}

} // Y_UNIT_TEST_SUITE(feature_api_fb_author_should)

Y_UNIT_TEST_SUITE(feature_api_similar_should)
{

Y_UNIT_TEST(get_features_similar)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/2/similar")
                .addParam("snap_to_road_graph", "true"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    auto json = json::Value::fromString(resp.body);
    EXPECT_EQ(json["data"]["features"].size(), 2u);
}


Y_UNIT_TEST(get_features_similar_graph_n_direction)
{
    /**
     * feature 9 is standalone
     * feature 10 is standalone
     * feature 13 relates to road graph
     * feature 14 relates to road graph (null), right
     * feature 15 relates to pedestrian graph
     */

    const struct {
        db::TId featureId;
        db::TIds featureIds;
    } TESTS[] = {
        {9, {10, 9}},
        {10, {10, 9}},
        {13, {13, 14}},
        {14, {14, 13}},
        {15, {15}},
    };

    MockedGraphFixture fixture;

    auto roadRelations = std::vector{makeRelation(13), makeRelation(14)};
    auto pedestrianRelations = std::vector{makeRelation(15)};

    ON_CALL(*fixture.roadPhotoToEdgeMock, lookupByFeatureId(13))
        .WillByDefault(::testing::Return(roadRelations));
    ON_CALL(*fixture.roadPhotoToEdgeMock, lookupByFeatureId(14))
        .WillByDefault(::testing::Return(roadRelations));
    ON_CALL(*fixture.pedestrianPhotoToEdgeMock, lookupByFeatureId(15))
        .WillByDefault(::testing::Return(pedestrianRelations));

    for (const auto& test : TESTS) {
        http::URL url("http://localhost/features/" +
                      std::to_string(test.featureId) + "/similar");
        http::MockRequest rq(http::GET, url);
        rq.headers.emplace(yacare::tests::USER_ID_HEADER, std::to_string(fixture.UID));
        auto resp = yacare::performTestRequest(rq);
        EXPECT_EQ(resp.status, 200) << " .featureId=" << test.featureId;
        auto json = json::Value::fromString(resp.body);
        EXPECT_THAT(
            collectIdsFromJson(json["data"]["features"]),
            test.featureIds);
    }
}


} // Y_UNIT_TEST_SUITE(feature_api_similar_should)

Y_UNIT_TEST_SUITE(feature_api_near_should)
{


Y_UNIT_TEST(get_features_near_with_edge)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET,
            http::URL("http://localhost/features/near?ll=37.546717,55.728255")
                .addParam("edge", "14587594604448499741")
                .addParam("snap_to_road_graph", "true"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    auto json = json::Value::fromString(resp.body);
    auto features = json["data"]["features"];
    EXPECT_EQ(features.size(), 1u);

    auto feature = features[0];
    auto id = feature["properties"]["id"];
    EXPECT_EQ(boost::lexical_cast<db::TId>(id.as<std::string>()), 11u);
}

Y_UNIT_TEST(get_features_near_without_edge)
{
    FixtureFb fixture;
    http::MockRequest rq(http::GET, http::URL("http://localhost/features/near?ll=37.546717,55.728255"));
    auto resp = yacare::performTestRequest(rq);
    EXPECT_EQ(resp.status, 200);
    auto json = json::Value::fromString(resp.body);
    auto features = json["data"]["features"];
    EXPECT_EQ(features.size(), 3u);
}

Y_UNIT_TEST(get_features_near_with_z)
{
    FixtureFb fixture;
    struct {
        int zoom;
        size_t count;
    } TESTS[] = {{0, 11u}, {1, 5u}, {9, 3u}};
    for (auto [zoom, count] : TESTS) {
        http::URL url{"http://localhost/features/near?ll=37.546717,55.728255"};
        url.addParam("z", zoom);
        http::MockRequest rq(http::GET, url);
        auto resp = yacare::performTestRequest(rq);
        ASSERT_EQ(resp.status, 200);
        auto json = json::Value::fromString(resp.body);
        auto features = json["data"]["features"];
        EXPECT_EQ(features.size(), count);
    }
}

Y_UNIT_TEST(get_features_near_graph)
{

    /**
     * feature 13 relates to road graph
     * feature 14 relates to road and pedestrian graphs
     * feature 15 relates to pedestrian graph
     */

    const struct {
        std::string graphType;
        db::TIds featureIds;
    } TESTS[] = {{"", {13, 14, 15}},
                //  {"road", {13, 14}},
                 {"pedestrian", {14, 15}}};

    MockedGraphFixtureFb fixture;

    ON_CALL(*fixture.roadGraphMock,
            getNearestCoveredEdges(testing::_, testing::_, testing::_))
        .WillByDefault(::testing::Return(
            std::vector{road_graph::EdgeId{13}, road_graph::EdgeId{14}}));

    ON_CALL(*fixture.pedestrianGraphMock,
            getNearestCoveredEdges(testing::_, testing::_, testing::_))
        .WillByDefault(::testing::Return(
            std::vector{road_graph::EdgeId{14}, road_graph::EdgeId{15}}));

    // edge has photo with same ID
    ON_CALL(*fixture.pedestrianGraphMock, getFeatureIdsByEdgeId)
        .WillByDefault(
            [](road_graph::EdgeId id) { return db::TIds{id.value()}; });

    for (const auto& test : TESTS) {
        http::URL url("http://localhost/features/near?ll=43.981049,56.215127");
        if (!test.graphType.empty()) {
            url.addParam("graph_type", test.graphType);
        }
        http::MockRequest rq(http::GET, url);
        rq.headers.emplace(yacare::tests::USER_ID_HEADER, std::to_string(fixture.UID));
        auto resp = yacare::performTestRequest(rq);
        EXPECT_EQ(resp.status, 200) << "for graph_type = " << test.graphType;
        auto json = json::Value::fromString(resp.body);
        EXPECT_THAT(
            collectIdsFromJson(json["data"]["features"]),
            ::testing::UnorderedElementsAreArray(test.featureIds));
    }
}

} // Y_UNIT_TEST_SUITE(feature_api_near_should)

Y_UNIT_TEST_SUITE(feature_api_path_should)
{

Y_UNIT_TEST(get_features_path_snap_to_graph)
{
    MockedGraphFixture fixture;

    auto noGraph = []() -> const road_graph::Graph& {
        throw RuntimeError{} << "no graph";
    };

    ON_CALL(*fixture.roadGraphMock, graph()).WillByDefault(noGraph);

    const struct {
        std::string graphType;
        int expectedStatus;
    } TESTS[] = {{"road", 500}, {"pedestrian", 200}};

    for (const auto& test : TESTS) {
        http::MockRequest rq(http::GET,
                             http::URL("http://localhost/features/2/path")
                                 .addParam("snap_to_road_graph", "true")
                                 .addParam("graph_type", test.graphType));
        EXPECT_EQ(yacare::performTestRequest(rq).status, test.expectedStatus);
    }
}

Y_UNIT_TEST(get_features_path_same_dates)
{
    auto features = db::Features{};
    for (int i = 0; i < 2; ++i) {
        features
            .emplace_back(db::feature::NO_SOURCE_ID,
                          geolib3::Point2{30.3229294910809, 59.9336919385615},
                          geolib3::Heading{344.146195141703},
                          "2021-05-12 14:47:00+03",
                          mds::Key("123", "path"),
                          db::Dataset::BackofficePhoto)
            .setSize({6, 9})
            .setAutomaticShouldBePublished(true)
            .setIsPublished(true);
    }

    auto fixture = FixtureFb{[&](pgpool3::Pool& pool) {
        auto txn = pool.masterWriteableTransaction();
        db::FeatureGateway{*txn}.insert(features);
        db::updateFeaturesTransaction(features, *txn);
        txn->commit();
        Playground::instance().makeCoverage();
    }};

    for (const auto& feature : features) {
        auto rq = http::MockRequest(
            http::GET,
            http::URL("http://localhost/features/" +
                      std::to_string(feature.id()) + "/path"));
        auto resp = yacare::performTestRequest(rq);
        EXPECT_EQ(resp.status, 200);
        auto json = json::Value::fromString(resp.body);
        EXPECT_EQ(json["data"]["features"].size(), 1u);
    }
}

} // Y_UNIT_TEST_SUITE(feature_api_path_should)

} // namespace maps::mrc::browser::tests
