#include <library/cpp/testing/common/env.h>
#include <library/cpp/testing/gtest/gtest.h>
#include <maps/wikimap/mapspro/services/mrc/long_tasks/toloka_manager_cron_jobs/lib/include/house_number_recognition.h>

namespace maps::mrc::toloka::test {

namespace {

const std::string TS_1 = "task-suite-id-1";
const std::string TS_2 = "task-suite-id-2";

const std::string POOL_ID = "1";

const std::string USER_1 = "user-id-1";
const std::string USER_2 = "user-id-2";
const std::string USER_3 = "user-id-3";

const std::string SOURCE_1 = "source-1";
const std::string SOURCE_2 = "source-2";
const std::string SOURCE_3 = "source-3";
const std::string SOURCE_4 = "source-4";
const std::string SOURCE_5 = "source-5";
const std::string SOURCE_6 = "source-6";

constexpr size_t OVERLAP = 3;

const common::ImageBox bbox(100, 100, 200, 200);

const std::string HOUSE_NUMBER_11 = "11";
const std::string HOUSE_NUMBER_22 = "22";
const std::string HOUSE_NUMBER_33 = "33";

} // anonymous namespace

TEST(house_number_recognition_tests, normalize_house_number)
{
    EXPECT_EQ(
        normalizeSymbolsInString(std::string{"a"}),
        std::string{"A"}
    );
    EXPECT_EQ(
        normalizeSymbolsInString(std::string{"д"}),
        std::string{"Д"}
    );
}

TEST(house_number_recognition_tests, merge_task_suites)
{
    HouseNumberRecognition::IdToTaskSuite idToTaskSuite{
        {TS_1,
         {TS_1,
          POOL_ID,
          OVERLAP,
          {HouseNumberRecognition::TaskInput(SOURCE_1, bbox),
           HouseNumberRecognition::TaskInput(SOURCE_2, bbox),
           HouseNumberRecognition::TaskInput(SOURCE_3, bbox),
           HouseNumberRecognition::TaskInput(SOURCE_4, bbox),
           HouseNumberRecognition::TaskInput(SOURCE_5, bbox)}}},
        {TS_2, {TS_2, POOL_ID, OVERLAP, {HouseNumberRecognition::TaskInput(SOURCE_6, bbox)}}}};

    HouseNumberRecognition::TaskSuiteIdToResults taskSuiteIdToResults{
        /** In task suite 1:
         *  task1 - all users agree it is "11"
         *  task2 - 2 users say it is "22", 1 user says it is "11"
         *  task3 - 3 users give 3 different answers
         *  task4 - not recognized by 2 users and not loaded for 1 user
         *  task5 - recognized as "33" by 1 user, and not recognized by 2 others
         */
        {TS_1,
         {{// Result from user 1
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_1,
           {HouseNumberRecognition::TaskInput(SOURCE_1, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_2, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_3, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_4, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_5, bbox)},
           {
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_11),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_22),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_11),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::NotRecognized),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_33), }},
          {// Result from user 2
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_2,
           {HouseNumberRecognition::TaskInput(SOURCE_1, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_2, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_3, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_4, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_5, bbox)},
           {HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_11),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_22),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_22),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::NotRecognized),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::NotRecognized)}},
          {// Result from user 3
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_3,
           {HouseNumberRecognition::TaskInput(SOURCE_1, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_2, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_3, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_4, bbox),
            HouseNumberRecognition::TaskInput(SOURCE_5, bbox)},
           {HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_11),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_11),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_33),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::NotLoaded),
            HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::NotRecognized)}}}},

        /** In task suite 2:
         *  Only 2 users accomplished the assignment, result is not ready
         */
        {TS_2,
         {{TS_2,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_1,
           {HouseNumberRecognition::TaskInput(SOURCE_6, bbox)},
           {HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_11)}},
          {TS_2,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_2,
           {HouseNumberRecognition::TaskInput(SOURCE_6, bbox)},
           {HouseNumberRecognition::TaskOutput(HouseNumberRecognition::TaskAnswer::Ok, HOUSE_NUMBER_11)}}}}};

    auto tsResults = mergeTasksResults<HouseNumberRecognition>(idToTaskSuite, taskSuiteIdToResults);

    // Validate recognition results
    // Results are available only for task suite 1, but not for
    // task suite 2, where not enough users have accomplished the assignments
    EXPECT_TRUE(tsResults.size() == 1) << "Wrong number of results";
    const auto& suiteResult = tsResults.begin()->second;
    const auto& taskResults = suiteResult.taskResults;

    EXPECT_TRUE(taskResults.size() == 5) << "Wrong number of tasks in task suite 1";

    EXPECT_EQ(taskResults[0].output.state(), HouseNumberRecognition::TaskAnswer::Ok);
    EXPECT_EQ(taskResults[0].output.houseNumber(), HOUSE_NUMBER_11);

    EXPECT_EQ(taskResults[1].output.state(), HouseNumberRecognition::TaskAnswer::Ok);
    EXPECT_EQ(taskResults[1].output.houseNumber(), HOUSE_NUMBER_22);

    EXPECT_EQ(taskResults[2].output.state(), HouseNumberRecognition::TaskAnswer::NotRecognized);
    EXPECT_EQ(taskResults[3].output.state(), HouseNumberRecognition::TaskAnswer::NotRecognized);
    EXPECT_EQ(taskResults[4].output.state(), HouseNumberRecognition::TaskAnswer::NotRecognized);
}

} // maps::mrc::toloka::test
