#include <maps/wikimap/mapspro/services/mrc/libs/yt/include/schema.h>
#include <maps/wikimap/mapspro/services/mrc/libs/yt/tests/small/object.h>

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

namespace maps::mrc::yt::tests {

Y_UNIT_TEST_SUITE(schema) {

Y_UNIT_TEST(get_type_of_base_types)
{
    UNIT_ASSERT_EQUAL(*getTypeOf<bool>(), *NTi::Bool());

    UNIT_ASSERT_EQUAL(*getTypeOf<int8_t>(), *NTi::Int8());
    UNIT_ASSERT_EQUAL(*getTypeOf<uint8_t>(), *NTi::Uint8());

    UNIT_ASSERT_EQUAL(*getTypeOf<int16_t>(), *NTi::Int16());
    UNIT_ASSERT_EQUAL(*getTypeOf<uint16_t>(), *NTi::Uint16());

    UNIT_ASSERT_EQUAL(*getTypeOf<int32_t>(), *NTi::Int32());
    UNIT_ASSERT_EQUAL(*getTypeOf<uint32_t>(), *NTi::Uint32());

    UNIT_ASSERT_EQUAL(*getTypeOf<int64_t>(), *NTi::Int64());
    UNIT_ASSERT_EQUAL(*getTypeOf<uint64_t>(), *NTi::Uint64());

    UNIT_ASSERT_EQUAL(*getTypeOf<float>(), *NTi::Double());
    UNIT_ASSERT_EQUAL(*getTypeOf<double>(), *NTi::Double());

    UNIT_ASSERT_EQUAL(*getTypeOf<std::string>(), *NTi::String());
}

Y_UNIT_TEST(get_type_of_complex_types)
{
    UNIT_ASSERT_EQUAL(*getTypeOf<json::Value>(), *NTi::String());

    UNIT_ASSERT_EQUAL(*getTypeOf<chrono::TimePoint>(), *NTi::Uint64());

    UNIT_ASSERT_EQUAL(*getTypeOf<std::chrono::seconds>(), *NTi::Int64());

    UNIT_ASSERT_EQUAL(*getTypeOf<common::ImageOrientation>(), *NTi::Int16());

    UNIT_ASSERT_EQUAL(*getTypeOf<common::ImageBox>(), *NTi::List(NTi::Uint64()));

    UNIT_ASSERT_EQUAL(*getTypeOf<SomeEnum>(), *NTi::String());

    UNIT_ASSERT_EQUAL(*getTypeOf<std::vector<double>>(), *NTi::List(NTi::Double()));

    UNIT_ASSERT_EQUAL(
        *getTypeOf<geolib3::Point2>(),
        *NTi::Struct({{"x", NTi::Double()}, {"y", NTi::Double()}})
    );
}

Y_UNIT_TEST(get_type_of_column)
{
    UNIT_ASSERT_EQUAL(*getTypeOf<sql_chemistry::Int64Column>(), *NTi::Int64());
    UNIT_ASSERT_EQUAL(*getTypeOf<sql_chemistry::NullableInt64Column>(), *NTi::Optional(NTi::Int64()));
}

Y_UNIT_TEST(get_type_of_serializabel)
{
    auto type = NTi::Struct({
        {"number", getTypeOf<int64_t>()},
        {"text", getTypeOf<std::string>()}
    });

    UNIT_ASSERT_EQUAL(*getTypeOf<mrc::Object>(), *type);
    UNIT_ASSERT_EQUAL(*getTypeOf<mrc::db::Object>(), *type);
}

Y_UNIT_TEST(get_schema_of_serializabel)
{
    const auto schema = NYT::TTableSchema()
        .AddColumn("number", getTypeOf<int64_t>())
        .AddColumn("text", getTypeOf<std::string>());

    UNIT_ASSERT_EQUAL(getSchemaOf<mrc::Object>(), schema);
    UNIT_ASSERT_EQUAL(getSchemaOf<mrc::db::Object>(), schema);
}

} // Y_UNIT_TEST_SUITE

} // namespace maps::mrc::yt::tests
