#include <library/cpp/testing/gtest/gtest.h>
#include <maps/wikimap/mapspro/services/mrc/tools/features_deleter/find_garbage.h>
#include <maps/wikimap/mapspro/services/mrc/tools/features_deleter/remove_features.h>
#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/feature_gateway.h>
#include <yandex/maps/mds/mds.h>
#include <yandex/maps/mrc/unittest/database_fixture.h>
#include <yandex/maps/mrc/unittest/local_server.h>
#include <yandex/maps/wiki/common/misc.h>

namespace maps {
namespace mrc {
namespace features_deleter {
namespace {

const std::string SOURCE = "src";
const std::string MDS_PATH = "photo_";
const std::string MDS_DATA = "dummy";
const std::string TEST_GRAPH_PATH = BinaryPath("maps/data/test/graph4");

struct FeatureData {
    geolib3::Point2 pos;
    geolib3::Heading heading;
    std::string date;
    std::string mdsGroup;
    std::string mdsPath;
    double quality;

    FeatureData(const geolib3::Point2& pos_,
                geolib3::Heading heading_,
                const std::string& date_,
                double quality_)
        : pos(pos_), heading(heading_), date(date_), quality(quality_)
    {
    }

    db::Feature toFeature() const
    {
        return sql_chemistry::GatewayAccess<db::Feature>::construct()
            .setSourceId(SOURCE)
            .setGeodeticPos(pos)
            .setHeading(heading)
            .setTimestamp(date)
            .setMdsKey({mdsGroup, mdsPath})
            .setDataset(db::Dataset::Rides)
            .setQuality(quality)
            .setSize(6, 9)
            .setAutomaticShouldBePublished(true)
            .setIsPublished(true);
    }
};

struct TestFixture : testing::Test,
                     unittest::WithUnittestConfig<unittest::DatabaseFixture,
                                                  unittest::MdsStubFixture> {
};

void save(pgpool3::Pool& pool,
          mds::Mds& mds,
          std::vector<FeatureData>& featuresData)
{
    for (size_t i = 0; i < featuresData.size(); ++i) {
        auto resp = mds.post(MDS_PATH + std::to_string(i), MDS_DATA);
        featuresData[i].mdsGroup = resp.key().groupId;
        featuresData[i].mdsPath = resp.key().path;
    }

    {
        auto txn = pool.masterWriteableTransaction();
        db::FeatureGateway gtw(*txn);
        db::Features features;
        for (const auto& data : featuresData) {
            features.push_back(data.toFeature());
        }
        gtw.insert(features);
        txn->commit();
    }
}

} // anonymous namespace

TEST_F(TestFixture, test_garbage)
{
    std::vector<FeatureData> featuresData
        = {FeatureData{
               {37.547148, 55.727823}, geolib3::Heading(170), "2016-09-01 10:00:00+03", 0.9},
           FeatureData{
               {37.547215, 55.727741}, geolib3::Heading(170), "2016-09-01 10:10:00+03", 0.01},
           FeatureData{
               {37.547282, 55.727659}, geolib3::Heading(170), "2016-09-01 10:20:00+03", 0.9}};
    auto mds = config().makeMdsClient();
    save(pool(), mds, featuresData);
    Context ctx(config(), TEST_GRAPH_PATH);
    auto featureIds = findGarbageFeatureIds(ctx);
    EXPECT_EQ(featureIds.size(), 1u);
    EXPECT_EQ(unpublishFeaturesByIds(ctx, featureIds), 1u);
    featureIds = findGarbageFeatureIds(ctx);
    EXPECT_EQ(featureIds.size(), 0u);
}

TEST_F(TestFixture, test_not_garbage)
{
    std::vector<FeatureData> featuresData
        = {FeatureData{
               {37.547148, 55.727823}, geolib3::Heading(170), "2016-09-01 10:00:00+03", 0.4},
           FeatureData{
               {37.547215, 55.727741}, geolib3::Heading(170), "2016-09-01 10:10:00+03", 0.01},
           FeatureData{
               {37.547282, 55.727659}, geolib3::Heading(170), "2016-09-01 10:20:00+03", 0.4}};
    auto mds = config().makeMdsClient();
    save(pool(), mds, featuresData);
    Context ctx(config(), TEST_GRAPH_PATH);
    auto featureIds = findGarbageFeatureIds(ctx);
    EXPECT_EQ(featureIds.size(), 0u);
}

} // features_deleter
} // mrc
} // maps
