#include <library/cpp/testing/common/env.h>
#include <library/cpp/testing/gtest/gtest.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/feature_gateway.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/ride_gateway.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/takeout_data_erasure_gateway.h>
#include <maps/wikimap/mapspro/services/mrc/long_tasks/async_takeout_data_erasure/lib/utility.h>
#include <maps/wikimap/mapspro/services/mrc/long_tasks/ride_inspector/lib/ride.h>
#include <yandex/maps/mrc/unittest/database_fixture.h>
#include <yandex/maps/mrc/unittest/unittest_config.h>

namespace maps::mrc::takeout_data_erasure {

namespace {

const auto SOURCE_ID = std::string{"iphone"};
const auto USER_ID = std::string{"100500"};

db::Feature makePhoto(chrono::TimePoint timePoint)
{
    return sql_chemistry::GatewayAccess<db::Feature>::construct()
        .setDataset(db::Dataset::Rides)
        .setSourceId(SOURCE_ID)
        .setTimestamp(timePoint)
        .setUserId(USER_ID);
}

}  // namespace

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

    TEST_F(Fixture, test_erasure)
    {
        using namespace std::literals::chrono_literals;

        auto startTime = chrono::TimePoint::clock::now() - 1h;
        auto endTime = startTime + 10s;
        auto requestedAt = startTime + (endTime - startTime) / 2;

        auto features = db::Features{
            makePhoto(startTime),
            makePhoto(requestedAt),
            makePhoto(endTime),
            makePhoto(endTime + 5s)  // not processed by inspector
        };

        auto ride = ride_inspector::makeRide(features.begin(), features.end());

        auto takeoutDataErasure =
            db::TakeoutDataErasure{{},  // takeout request id
                                   USER_ID,
                                   requestedAt};

        {
            auto txn = pool().masterWriteableTransaction();
            db::FeatureGateway{*txn}.insert(features);
            db::RideGateway{*txn}.insertx(ride);
            db::TakeoutDataErasureGateway{*txn}.insert(takeoutDataErasure);
            txn->commit();
        }

        EXPECT_EQ(db::FeatureGateway{*pool().masterReadOnlyTransaction()}.count(
                      db::table::Feature::userId == USER_ID and
                      not db::table::Feature::gdprDeleted.is(true)),
                  4u);

        EXPECT_TRUE(db::RideGateway{*pool().masterReadOnlyTransaction()}.exists(
            db::table::Ride::userId == USER_ID and
            db::table::Ride::startTime <= takeoutDataErasure.requestedAt() and
            not db::table::Ride::isDeleted));

        erasure(pool(), takeoutDataErasure.id());

        auto photoIds =
            db::FeatureGateway{*pool().masterReadOnlyTransaction()}.loadIds(
                db::table::Feature::userId == USER_ID and
                not db::table::Feature::gdprDeleted.is(true));
        EXPECT_EQ(photoIds.size(), 2u);
        auto expect = {features[2].id(), features[3].id()};
        EXPECT_TRUE(std::is_permutation(
            photoIds.begin(), photoIds.end(), expect.begin(), expect.end()));

        EXPECT_FALSE(
            db::RideGateway{*pool().masterReadOnlyTransaction()}.exists(
                db::table::Ride::userId == USER_ID and
                db::table::Ride::startTime <=
                    takeoutDataErasure.requestedAt() and
                not db::table::Ride::isDeleted));
    }

}  // namespace maps::mrc::takeout_data_erasure
