#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/detection_pair_match.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_1 = "source-1-1";
const std::string SOURCE_1_2 = "source-1-2";
const std::string SOURCE_2_1 = "source-2-1";
const std::string SOURCE_2_2 = "source-2-2";
const std::string SOURCE_3_1 = "source-3-1";
const std::string SOURCE_3_2 = "source-3-2";
const std::string SOURCE_4_1 = "source-4-1";
const std::string SOURCE_4_2 = "source-4-2";
const std::string SOURCE_5_1 = "source-5-1";
const std::string SOURCE_5_2 = "source-5-2";
const std::string SOURCE_6_1 = "source-6-1";
const std::string SOURCE_6_2 = "source-6-2";

constexpr size_t OVERLAP = 3;

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

} // namespace

TEST(detection_pair_match_tests, merge_task_suites)
{
    DetectionPairMatch::IdToTaskSuite idToTaskSuite{
        {TS_1,
         {TS_1,
          POOL_ID,
          OVERLAP,
          {DetectionPairMatch::TaskInput(SOURCE_1_1, bbox, SOURCE_1_2, bbox),
           DetectionPairMatch::TaskInput(SOURCE_2_1, bbox, SOURCE_2_2, bbox),
           DetectionPairMatch::TaskInput(SOURCE_3_1, bbox, SOURCE_3_2, bbox),
           DetectionPairMatch::TaskInput(SOURCE_4_1, bbox, SOURCE_4_2, bbox),
           DetectionPairMatch::TaskInput(SOURCE_5_1, bbox, SOURCE_5_2, bbox)}}},
        {TS_2,
         {TS_2,
          POOL_ID,
          OVERLAP,
          {DetectionPairMatch::TaskInput(SOURCE_6_1, bbox, SOURCE_6_2, bbox)}}}
    };

    DetectionPairMatch::TaskSuiteIdToResults taskSuiteIdToResults{
        {TS_1,
         {{// Result from user 1
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_1,
           {DetectionPairMatch::TaskInput(SOURCE_1_1, bbox, SOURCE_1_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_2_1, bbox, SOURCE_2_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_3_1, bbox, SOURCE_3_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_4_1, bbox, SOURCE_4_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_5_1, bbox, SOURCE_5_2, bbox)},
           {
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::NotLoaded),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes)}},
          {// Result from user 2
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_2,
           {DetectionPairMatch::TaskInput(SOURCE_1_1, bbox, SOURCE_1_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_2_1, bbox, SOURCE_2_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_3_1, bbox, SOURCE_3_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_4_1, bbox, SOURCE_4_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_5_1, bbox, SOURCE_5_2, bbox)},
           {DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::NotLoaded)}},
          {// Result from user 3
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_3,
           {DetectionPairMatch::TaskInput(SOURCE_1_1, bbox, SOURCE_1_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_2_1, bbox, SOURCE_2_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_3_1, bbox, SOURCE_3_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_4_1, bbox, SOURCE_4_2, bbox),
            DetectionPairMatch::TaskInput(SOURCE_5_1, bbox, SOURCE_5_2, bbox)},
           {DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::No),
            DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::NotLoaded)}}}},

        {TS_2,
         {{TS_2,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_1,
           {DetectionPairMatch::TaskInput(SOURCE_6_1, bbox, SOURCE_6_2, bbox)},
           {DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes)}},
          {TS_2,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_2,
           {DetectionPairMatch::TaskInput(SOURCE_6_1, bbox, SOURCE_6_2, bbox)},
           {DetectionPairMatch::TaskOutput(DetectionPairMatch::TaskAnswer::Yes)}}}}};

    auto tsResults = mergeTasksResults<DetectionPairMatch>(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.result(), DetectionPairMatch::TaskAnswer::Yes);

    EXPECT_EQ(taskResults[1].output.result(), DetectionPairMatch::TaskAnswer::Yes);

    EXPECT_EQ(taskResults[2].output.result(), DetectionPairMatch::TaskAnswer::Yes);
    EXPECT_EQ(taskResults[3].output.result(), DetectionPairMatch::TaskAnswer::Unknown);
    EXPECT_EQ(taskResults[4].output.result(), DetectionPairMatch::TaskAnswer::NotLoaded);
}

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