#include <maps/wikimap/mapspro/services/mrc/eye/experiments/signs_map/lib/datasets/include/dataset.h>
#include <maps/wikimap/mapspro/services/mrc/eye/experiments/signs_map/lib/datasets/include/objects.h>

#include <mapreduce/yt/tests/yt_unittest_lib/yt_unittest_lib.h>

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

namespace maps::mrc::eye::datasets::tests {

Y_UNIT_TEST_SUITE(objects_tests)
{

Y_UNIT_TEST(item_yt)
{
    const db::TId featureId = 1;
    const Objects objects{
        {
            1, common::ImageBox(1, 2, 3, 4),
            traffic_signs::TrafficSign::ProhibitoryMaxSpeed80
        },
        {
            2, common::ImageBox(2, 3, 4, 5),
            traffic_signs::TrafficSign::ProhibitoryMaxSpeed20
        }
    };

    NYT::TNode node = toNode(featureId, objects);

    const auto& [resultFeatureId, resultObjects]
        = fromNode<db::TId,Objects>(node);

    EXPECT_EQ(featureId, resultFeatureId);
    EXPECT_TRUE(objects == resultObjects);
}

Y_UNIT_TEST(item_json)
{
    const db::TId featureId = 1;
    const Objects objects{
        {
            1, common::ImageBox(1, 2, 3, 4),
            traffic_signs::TrafficSign::ProhibitoryMaxSpeed80
        },
        {
            2, common::ImageBox(2, 3, 4, 5),
            traffic_signs::TrafficSign::ProhibitoryMaxSpeed20
        }
    };

    json::Value value = toJson(featureId, objects);

    const auto& [resultFeatureId, resultObjects]
        = fromJson<db::TId, Objects>(value);

    EXPECT_EQ(featureId, resultFeatureId);
    EXPECT_TRUE(objects == resultObjects);
}

Y_UNIT_TEST(write_read_yt)
{
    NYT::IClientPtr client = NYT::NTesting::CreateTestClient();
    const std::string tablePath = "//home/dataset";
    const ObjectsDataset dataset({
        {
            1,
            Objects{
                {
                    1, common::ImageBox(1, 2, 3, 4),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed80
                },
                {
                    2, common::ImageBox(2, 3, 4, 5),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed20
                }
            }
        },
        {
            2,
            Objects{
                {
                    1, common::ImageBox(3, 4, 5, 6),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed40
                },
                {
                    2, common::ImageBox(4, 5, 6, 7),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed60
                }
            }

        }
    });
    dataset.writeToYT(client, tablePath);

    ObjectsDataset resultDataset;
    resultDataset.readFromYT(client, tablePath);

    EXPECT_EQ(dataset.data(), resultDataset.data());

    client->Remove(NYT::TYPath(tablePath));
}

Y_UNIT_TEST(write_read_json)
{
    const ObjectsDataset dataset({
        {
            1,
            Objects{
                {
                    1, common::ImageBox(1, 2, 3, 4),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed80
                },
                {
                    2, common::ImageBox(2, 3, 4, 5),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed20
                }
            }
        },
        {
            2,
            Objects{
                {
                    1, common::ImageBox(3, 4, 5, 6),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed40
                },
                {
                    2, common::ImageBox(4, 5, 6, 7),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed60
                }
            }

        }
    });
    std::stringstream ss;
    dataset.writeToJson(ss);

    ObjectsDataset resultDataset;
    resultDataset.readFromJson(ss);

    EXPECT_EQ(dataset.data(), resultDataset.data());
}

Y_UNIT_TEST(upload_yt)
{
    NYT::IClientPtr client = NYT::NTesting::CreateTestClient();
    const std::string tablePath = "//home/dataset";
    const ObjectsDataset dataset({
        {
            1,
            Objects{
                {
                    1, common::ImageBox(1, 2, 3, 4),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed80
                },
                {
                    2, common::ImageBox(2, 3, 4, 5),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed20
                }
            }
        },
        {
            2,
            Objects{
                {
                    1, common::ImageBox(3, 4, 5, 6),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed40
                },
                {
                    2, common::ImageBox(4, 5, 6, 7),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed60
                }
            }

        }
    });
    std::stringstream ss;
    dataset.writeToJson(ss);

    ObjectsDataset::uploadToYT(client, ss, tablePath);

    ObjectsDataset resultDataset;
    resultDataset.readFromYT(client, tablePath);

    EXPECT_EQ(dataset.data(), resultDataset.data());

    client->Remove(NYT::TYPath(tablePath));
}

Y_UNIT_TEST(download_yt)
{
    NYT::IClientPtr client = NYT::NTesting::CreateTestClient();
    const std::string tablePath = "//home/dataset";
    const ObjectsDataset dataset({
        {
            1,
            Objects{
                {
                    1, common::ImageBox(1, 2, 3, 4),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed80
                },
                {
                    2, common::ImageBox(2, 3, 4, 5),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed20
                }
            }
        },
        {
            2,
            Objects{
                {
                    1, common::ImageBox(3, 4, 5, 6),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed40
                },
                {
                    2, common::ImageBox(4, 5, 6, 7),
                    traffic_signs::TrafficSign::ProhibitoryMaxSpeed60
                }
            }

        }
    });
    dataset.writeToYT(client, tablePath);

    std::stringstream ss;
    ObjectsDataset::downloadFromYT(client, ss, tablePath);

    ObjectsDataset resultDataset;
    resultDataset.readFromJson(ss);

    EXPECT_EQ(dataset.data(), resultDataset.data());

    client->Remove(NYT::TYPath(tablePath));
}

} // Y_UNIT_TEST_SUITE

} // namespace maps::mrc::eye::datasets::tests
