#include <maps/wikimap/mapspro/services/mrc/eye/lib/detect_road_marking/tests/fixture.h>

#include <maps/wikimap/mapspro/services/mrc/eye/lib/detect_road_marking/impl/serialize.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/detect_road_marking/impl/strings.h>

#include <maps/wikimap/mapspro/services/mrc/eye/lib/location/include/rotation.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/unit_test/include/frame.h>

#include <library/cpp/testing/unittest/registar.h>
#include <mapreduce/yt/tests/yt_unittest_lib/yt_unittest_lib.h>

#include <maps/wikimap/mapspro/services/mrc/libs/yt/include/io.h>

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

struct SerializeFixture : public Fixture {
    SerializeFixture() {
        auto txn = newTxn();

        devices = {
            {db::eye::MrcDeviceAttrs{"M1"}},
        };
        db::eye::DeviceGateway(*txn).insertx(devices);

        frames = {
            {devices[0].id(), identical, makeUrlContext(1, "1"), {1200, 800}, time()},
            {devices[0].id(), identical, makeUrlContext(2, "2"), {1200, 800}, time()},
            {devices[0].id(), identical, makeUrlContext(3, "3"), {1200, 800}, time()},
        };
        db::eye::FrameGateway(*txn).insertx(frames);

        recognitions = {
            {
                frames[0].id(),
                frames[0].orientation(),
                db::eye::RecognitionType::DetectPanel,
                db::eye::RecognitionSource::Model,
                0, // version
                db::eye::DetectedPanel{}
            },
            {
                frames[2].id(),
                frames[2].orientation(),
                db::eye::RecognitionType::DetectPanel,
                db::eye::RecognitionSource::Model,
                0, // version
                db::eye::DetectedPanel{}
            },
        };
        db::eye::RecognitionGateway(*txn).insertx(recognitions);

        txn->commit();
    }
};

Y_UNIT_TEST_SUITE_F(serialize_tests, SerializeFixture)
{

Y_UNIT_TEST(base)
{
    NYT::IClientPtr client = NYT::NTesting::CreateTestClient();
    NYT::ITransactionPtr ytTxn = client->StartTransaction();

    const TString tablePath = "//home/frames";
    const db::IdTo<db::eye::Frame> frameById{
        {frames[0].id(), frames[0]},
        {frames[1].id(), frames[1]},
        {frames[2].id(), frames[2]},
    };
    const db::IdTo<db::eye::Recognition> panelByFrameId{
        {frames[0].id(), recognitions[0]},
        {frames[2].id(), recognitions[1]},
    };

    writeFrames(ytTxn, tablePath, frameById, panelByFrameId);

    NYT::TTableReaderPtr<NYT::TNode> reader
        = ytTxn->CreateTableReader<NYT::TNode>(tablePath);

    std::vector<std::pair<db::eye::Frame, db::eye::Recognition>> result;
    for (; reader->IsValid(); reader->Next()) {
        const NYT::TNode row = reader->GetRow();
        const auto frame = yt::deserialize<db::eye::Frame>(row[FRAME_COLUMN]);
        const auto panel = yt::deserialize<db::eye::Recognition>(row[PANEL_COLUMN]);

        result.emplace_back(frame, panel);
    }

    std::sort(result.begin(), result.end(),
        [](const auto& lhs, const auto& rhs) {
            return lhs.first.id() < rhs.first.id();
        }
    );

    UNIT_ASSERT_EQUAL(result.size(), 2u);

    UNIT_ASSERT_EQUAL(result[0].first.introspect(), frames[0].introspect());
    UNIT_ASSERT_EQUAL(result[1].first.introspect(), frames[2].introspect());

    UNIT_ASSERT_EQUAL(result[0].second.introspect(), recognitions[0].introspect());
    UNIT_ASSERT_EQUAL(result[1].second.introspect(), recognitions[1].introspect());
}

} // Y_UNIT_TEST_SUITE

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