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

#include <maps/wikimap/mapspro/services/mrc/eye/lib/detect_panel/include/detect_panel.h>

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

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

Y_UNIT_TEST_SUITE_F(full_stack, Fixture)
{

Y_UNIT_TEST(run)
{
    const auto loader = FrameLoader::fromConfig(config());
    const auto yt = NYT::NTesting::CreateTestClient();

    const size_t beforeN = countRecognitions();

    DetectPanelConfig workerConfig;
    workerConfig.yt.client = yt.Get();
    workerConfig.yt.concurrency = 1;
    workerConfig.yt.frameLoader = &loader;
    workerConfig.yt.partitionSize = 10;
    workerConfig.yt.rootPath = "//tmp/full_stack/run";
    workerConfig.mrc.pool = &pool();
    workerConfig.mrc.commit = true;
    workerConfig.margin = 3;

    DetectPanel detect(workerConfig);

    detect.processBatch(frameIdsAt({0, 1, 2, 3, 4, 5, 6, 7, 8, 9}));

    const size_t afterN = countRecognitions();
    UNIT_ASSERT_EQUAL(beforeN + 10, afterN);

    constexpr size_t width = 284;
    constexpr size_t height = 160;

    {
        const auto recognition = recognitionForFrameAt(0);

        UNIT_ASSERT(recognition.txnId());
        UNIT_ASSERT_EQUAL(recognition.orientation(), common::ImageOrientation::fromExif(1));
        UNIT_ASSERT_EQUAL(recognition.type(), db::eye::RecognitionType::DetectPanel);
        UNIT_ASSERT_EQUAL(recognition.source(), db::eye::RecognitionSource::Model);
        UNIT_ASSERT_EQUAL(recognition.version(), DetectPanel::version);

        const auto detection = recognition.value<db::eye::DetectedPanel>();
        const common::ImageBox box = detection.restBox;

        UNIT_ASSERT(
            box.minX() == 0 and box.minY() == 0
                    and box.maxX() == width and box.maxY() >= 120
        );
    }

    {
        const auto recognition = recognitionForFrameAt(6);

        UNIT_ASSERT(recognition.txnId());
        UNIT_ASSERT_EQUAL(recognition.orientation(), common::ImageOrientation::fromExif(3));
        UNIT_ASSERT_EQUAL(recognition.type(), db::eye::RecognitionType::DetectPanel);
        UNIT_ASSERT_EQUAL(recognition.source(), db::eye::RecognitionSource::Model);
        UNIT_ASSERT_EQUAL(recognition.version(), DetectPanel::version);

        const auto detection = recognition.value<db::eye::DetectedPanel>();
        const common::ImageBox box = detection.restBox;

        UNIT_ASSERT(
            box.minX() == 0 and box.minY() <= 40
                and box.maxX() == width and box.maxY() == height
        );
    }
}

Y_UNIT_TEST(version_conflict)
{
    const auto loader = FrameLoader::fromConfig(config());
    const auto yt = NYT::NTesting::CreateTestClient();

    DetectPanelConfig workerConfig;
    workerConfig.yt.client = yt.Get();
    workerConfig.yt.concurrency = 1;
    workerConfig.yt.frameLoader = &loader;
    workerConfig.yt.partitionSize = 10;
    workerConfig.yt.rootPath = "//tmp/full_stack/detect_panel_batch";
    workerConfig.mrc.pool = &pool();
    workerConfig.mrc.commit = true;
    workerConfig.margin = 3;

    DetectPanel detect(workerConfig);

    detect.processBatch(frameIdsAt({0, 1, 2, 3, 4}));
    UNIT_ASSERT_EXCEPTION(
        detect.processBatch(frameIdsAt({0, 1, 2, 3, 4})),
        sql_chemistry::UniqueViolationError
    );
}

Y_UNIT_TEST(batch)
{
    const auto loader = FrameLoader::fromConfig(config());
    const auto yt = NYT::NTesting::CreateTestClient();

    DetectPanelConfig workerConfig;
    workerConfig.yt.client = yt.Get();
    workerConfig.yt.concurrency = 1;
    workerConfig.yt.frameLoader = &loader;
    workerConfig.yt.partitionSize = 10;
    workerConfig.yt.rootPath = "//tmp/full_stack/detect_panel_batch";
    workerConfig.mrc.pool = &pool();
    workerConfig.mrc.commit = true;
    workerConfig.margin = 3;

    DetectPanel detect(workerConfig);

    UNIT_ASSERT_EQUAL(detect.processBatchInLoopMode(5), true);
    UNIT_ASSERT_EQUAL(detect.processBatchInLoopMode(10), true);
}

} // Y_UNIT_TEST_SUITE

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