#include "construct.h"
#include "fixture.h"

#include <library/cpp/testing/gtest/gtest.h>
#include <maps/libs/introspection/include/comparison.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/disqualified_source_gateway.h>
#include <yandex/maps/mrc/unittest/unittest_config.h>

#include <random>

namespace maps::mrc::db {
using introspection::operator==;
}  // namespace maps::mrc::db

namespace maps::mrc::db::tests {
using namespace ::testing;
using namespace std::literals::chrono_literals;
namespace {

const auto SRC = std::string{"Xiaomi"};

auto& randomNumberEngine()
{
    static auto result = std::mt19937{std::random_device{}()};
    return result;
}

chrono::TimePoint time(std::chrono::minutes minutes)
{
    static auto date = chrono::parseSqlDateTime("2022-04-22 15:50:00+03");
    return date + minutes;
}

}  // namespace

TEST_F(Fixture, test_disqualified_source_read_write)
{
    auto disqs = DisqualifiedSources{
        DisqualifiedSource{DisqType::DisableCapturing, SRC, time(1h), time(2h)},
        DisqualifiedSource{
            DisqType::DisablePublishing, SRC, time(1h), time(3h)},
        DisqualifiedSource{DisqType::DisableCapturing, SRC, time(4h), time(5h)},
        DisqualifiedSource{DisqType::DisablePublishing, SRC, time(4h)},
    };
    std::shuffle(disqs.begin(), disqs.end(), randomNumberEngine());
    {
        auto txn = txnHandle();
        DisqualifiedSourceGateway{*txn}.insert(disqs);
        txn->commit();
    }
    EXPECT_EQ(DisqualifiedSourceGateway{*txnHandle()}.load(), disqs);

    disqs = DisqualifiedSourceGateway{*txnHandle()}.load(
        table::DisqualifiedSource::sourceId == SRC,
        orderBy(table::DisqualifiedSource::endedAt).desc().limit(2));
    EXPECT_EQ(disqs.size(), 2u);
    EXPECT_FALSE(disqs.front().endedAt().has_value());
    EXPECT_EQ(disqs.back().endedAt(), time(5h));

    {
        disqs.front().setEndedAt(time(6h));
        auto txn = txnHandle();
        DisqualifiedSourceGateway{*txn}.update(disqs);
        txn->commit();
    }

    disqs = DisqualifiedSourceGateway{*txnHandle()}.load(
        table::DisqualifiedSource::sourceId == SRC,
        orderBy(table::DisqualifiedSource::endedAt).desc().limit(2));
    EXPECT_EQ(disqs.size(), 2u);
    EXPECT_EQ(disqs.front().endedAt(), time(6h));
    EXPECT_EQ(disqs.back().endedAt(), time(5h));
}

TEST_F(Fixture, test_disqualified_source_unique_null)
{
    auto disqs = DisqualifiedSources{
        DisqualifiedSource{DisqType::DisablePublishing, SRC, time(1h)},
        DisqualifiedSource{DisqType::DisablePublishing, SRC, time(2h)},
    };
    EXPECT_THROW(DisqualifiedSourceGateway{*txnHandle()}.insert(disqs),
                 sql_chemistry::UniqueViolationError);
}

}  // namespace maps::mrc::db::tests
