#include <maps/wikimap/mapspro/services/mrc/eye/lib/recognition_task/tests/fixture.h>
#include <maps/wikimap/mapspro/services/mrc/eye/lib/recognition_task/include/manager.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/eye/recognition_gateway.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/eye/recognition_value.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/toloka/task_gateway.h>
#include <maps/libs/http/include/test_utils.h>

using namespace maps::mrc::db::eye;
using namespace maps::mrc::db::toloka;

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

TEST_F(Fixture, manager_base_test)
{
    // prepare database
    auto txn = txnHandle();

    Recognitions recognitions = {
        {
            frames[0].id(),
            common::ImageOrientation(common::Rotation::CW_0),
            RecognitionType::DetectTrafficLight,
            RecognitionSource::Toloka,
            1
        },
        {
            frames[1].id(),
            common::ImageOrientation(common::Rotation::CW_90),
            RecognitionType::DetectSign,
            RecognitionSource::Model,
            1
        },
        {
            frames[2].id(),
            common::ImageOrientation(common::Rotation::CW_180),
            RecognitionType::DetectTrafficLight,
            RecognitionSource::Toloka,
            1
        },
        {
            frames[2].id(),
            common::ImageOrientation(common::Rotation::CW_90),
            RecognitionType::DetectTrafficLight,
            RecognitionSource::Toloka,
            1
        },
    };
    recognitions[3].setValue(DetectedTrafficLights({}));
    RecognitionGateway(*txn).insertx(recognitions);

    Tasks tasks = {
        {
            Task(db::toloka::Platform::Toloka)
                  .setType(TaskType::TrafficLightDetection)
                  .setStatus(TaskStatus::Finished)
                  .setInputValues(R"({"image": "https://yandex.ru/image-1"})")
                  .setOutputValues(R"(
                      {
                          "result": "is_not_empty",
                          "polygons": [
                              {
                                  "type": "rectangle",
                                  "data": {
                                      "p1": {"x": 0.0078125, "y": 0.013888889},
                                      "p2": {"x": 0.0156250, "y": 0.027777778}
                                  }
                              }
                          ]
                      }
                  )")
        },
    };
    TaskGateway(*txn).insertx(tasks);

    RecognitionTasks recognitionTasks = {
        {
            recognitions[0].id(),
            tasks[0].id()
        }
    };
    RecognitionTaskGateway(*txn).insertx(recognitionTasks);

    txn->commit();

    // test
    const size_t batchSize = 10;

    FrameUrlResolver urlResolver(
        "http://fake-browser-mrc.yandex.ru",
        "http://fake-browser-pro-mrc.yandex.ru");

    RecognitionTaskManagerConfig config;
    config.mrc.lockFree = true;
    config.mrc.commit = true;
    config.mrc.pool = &pool();
    config.frameUrlResolver = &urlResolver;
    config.recognitionTypes = {RecognitionType::DetectTrafficLight};

    RecognitionTaskManager manager(config);

    EXPECT_EQ(manager.processBatchInLoopMode(batchSize), true);

    {
        auto txn = txnHandle();

        RecognitionTasks recognitionTasks = RecognitionTaskGateway(*txn).load(
            db::eye::table::RecognitionTask::recognitionId == recognitions[2].id()
        );
        EXPECT_EQ(recognitionTasks.size(), 1u);
        RecognitionTask& recognitionTask = recognitionTasks[0];
        db::toloka::Task task = db::toloka::TaskGateway(*txn).loadById(recognitionTask.taskId());

        task.setOutputValues(R"(
            {
                "result": "is_not_empty",
                "polygons": [
                    {
                        "type": "rectangle",
                        "data": {
                            "p1": {"x": 0.0156250, "y": 0.027777778},
                            "p2": {"x": 0.0234375, "y": 0.041666667}
                        }
                    }
                ]
            }
        )");
        db::toloka::TaskGateway(*txn).updatex(task);

        txn->commit();
    }

    EXPECT_EQ(manager.processBatchInLoopMode(batchSize), true);

    {
        Recognition recognition = RecognitionGateway(*txnHandle()).loadById(recognitions[0].id());
        EXPECT_TRUE(recognition.hasValue());
        EXPECT_EQ(
            recognition.value<DetectedTrafficLights>().size(),
            1u
        );
        EXPECT_EQ(
            recognition.value<DetectedTrafficLights>()[0].box,
            common::ImageBox(10, 10, 20, 20)
        );
        EXPECT_TRUE(recognitions[0].txnId() < recognition.txnId());
    }

    {
        Recognition recognition = RecognitionGateway(*txnHandle()).loadById(recognitions[2].id());
        EXPECT_TRUE(recognition.hasValue());
        EXPECT_EQ(
            recognition.value<DetectedTrafficLights>().size(),
            1u
        );

        EXPECT_EQ(
            recognition.value<DetectedTrafficLights>()[0].box,
            common::revertByImageOrientation(
                common::ImageBox(20, 20, 30, 30),
                frames[2].originalSize(),
                recognitions[2].orientation()
            )
        );
        EXPECT_TRUE(recognitions[2].txnId() < recognition.txnId());
    }
}

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