#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/approvement.h>
#include <maps/libs/geolib/include/point.h>

namespace maps {
namespace mrc {
namespace toloka {
namespace 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 std::vector<common::ImageBox> bboxes{{100, 100, 200, 200}};

} // anonymous namespace

TEST(approvement_test, merge_task_suites)
{
    Approvement::IdToTaskSuite idToTaskSuite{
        {TS_1,
         {TS_1,
          POOL_ID,
          OVERLAP,
          {Approvement::TaskInput(SOURCE_1, bboxes),
           Approvement::TaskInput(SOURCE_2, bboxes),
           Approvement::TaskInput(SOURCE_3, bboxes),
           Approvement::TaskInput(SOURCE_4, bboxes),
           Approvement::TaskInput(SOURCE_5, bboxes)}}},
        {TS_2, {TS_2, POOL_ID, OVERLAP, {Approvement::TaskInput(SOURCE_6, bboxes)}}}};

    Approvement::TaskSuiteIdToResults taskSuiteIdToResults{
        /** In task suite 1:
         *  task1 - all users agree it is 'yes'
         *  task2 - 2 users say it is 'no', 1 user says it is
         * 'not-loaded'
         *  task3 - 3 users give 3 different answers
         *  task4 - 'yes' by 2 users and 'not-loaded' by 1 user
         *  task5 - classified as 'no' by 1 user, and 'not-loaded' by
         * 2 others
         */
        {TS_1,
         {{// Result from user 1
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_1,
           {Approvement::TaskInput(SOURCE_1, bboxes),
            Approvement::TaskInput(SOURCE_2, bboxes),
            Approvement::TaskInput(SOURCE_3, bboxes),
            Approvement::TaskInput(SOURCE_4, bboxes),
            Approvement::TaskInput(SOURCE_5, bboxes)},
           {Approvement::TaskOutput(Approvement::TaskAnswer::Yes),
            Approvement::TaskOutput(Approvement::TaskAnswer::No),
            Approvement::TaskOutput(Approvement::TaskAnswer::Yes),
            Approvement::TaskOutput(Approvement::TaskAnswer::Yes),
            Approvement::TaskOutput(Approvement::TaskAnswer::No)}},
          {// Result from user 2
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_2,
           {Approvement::TaskInput(SOURCE_1, bboxes),
            Approvement::TaskInput(SOURCE_2, bboxes),
            Approvement::TaskInput(SOURCE_3, bboxes),
            Approvement::TaskInput(SOURCE_4, bboxes),
            Approvement::TaskInput(SOURCE_5, bboxes)},
           {Approvement::TaskOutput(Approvement::TaskAnswer::Yes),
            Approvement::TaskOutput(Approvement::TaskAnswer::No),
            Approvement::TaskOutput(Approvement::TaskAnswer::No),
            Approvement::TaskOutput(Approvement::TaskAnswer::Yes),
            Approvement::TaskOutput(Approvement::TaskAnswer::NotLoaded)}},
          {// Result from user 3
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_3,
           {Approvement::TaskInput(SOURCE_1, bboxes),
            Approvement::TaskInput(SOURCE_2, bboxes),
            Approvement::TaskInput(SOURCE_3, bboxes),
            Approvement::TaskInput(SOURCE_4, bboxes),
            Approvement::TaskInput(SOURCE_5, bboxes)},
           {Approvement::TaskOutput(Approvement::TaskAnswer::Yes),
            Approvement::TaskOutput(Approvement::TaskAnswer::NotLoaded),
            Approvement::TaskOutput(Approvement::TaskAnswer::NotLoaded),
            Approvement::TaskOutput(Approvement::TaskAnswer::NotLoaded),
            Approvement::TaskOutput(Approvement::TaskAnswer::NotLoaded)}}}},

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

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

    // Validate approvement 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.answer(), Approvement::TaskAnswer::Yes);
    EXPECT_EQ(taskResults[1].output.answer(), Approvement::TaskAnswer::No);
    EXPECT_EQ(taskResults[2].output.answer(), Approvement::TaskAnswer::No);
    EXPECT_EQ(taskResults[3].output.answer(), Approvement::TaskAnswer::Yes);
    EXPECT_EQ(taskResults[4].output.answer(), Approvement::TaskAnswer::NotLoaded);

    // Validate user statistics
    const auto& stat1 = suiteResult.userIdToStat.at(USER_1);
    const auto& stat2 = suiteResult.userIdToStat.at(USER_2);
    const auto& stat3 = suiteResult.userIdToStat.at(USER_3);

    EXPECT_EQ(stat1.tasksCount, 5u);
    EXPECT_EQ(stat1.correctCount, 3);

    EXPECT_EQ(stat2.tasksCount, 5u);
    EXPECT_EQ(stat2.correctCount, 4);

    EXPECT_EQ(stat3.tasksCount, 5u);
    EXPECT_EQ(stat3.correctCount, 2);
}

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