#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_missing_on_frame.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_missing_on_frame_tests, merge_task_suites)
{
    DetectionMissingOnFrame::IdToTaskSuite idToTaskSuite{
        {TS_1,
         {TS_1,
          POOL_ID,
          OVERLAP,
          {DetectionMissingOnFrame::TaskInput(SOURCE_1_1, bbox, SOURCE_1_2),
           DetectionMissingOnFrame::TaskInput(SOURCE_2_1, bbox, SOURCE_2_2),
           DetectionMissingOnFrame::TaskInput(SOURCE_3_1, bbox, SOURCE_3_2),
           DetectionMissingOnFrame::TaskInput(SOURCE_4_1, bbox, SOURCE_4_2),
           DetectionMissingOnFrame::TaskInput(SOURCE_5_1, bbox, SOURCE_5_2)}}},
        {TS_2,
         {TS_2,
          POOL_ID,
          OVERLAP,
          {DetectionMissingOnFrame::TaskInput(SOURCE_6_1, bbox, SOURCE_6_2)}}}
    };

    DetectionMissingOnFrame::TaskSuiteIdToResults taskSuiteIdToResults{
        {TS_1,
         {{// Result from user 1
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_1,
           {DetectionMissingOnFrame::TaskInput(SOURCE_1_1, bbox, SOURCE_1_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_2_1, bbox, SOURCE_2_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_3_1, bbox, SOURCE_3_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_4_1, bbox, SOURCE_4_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_5_1, bbox, SOURCE_5_2)},
           {
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                std::nullopt
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                std::nullopt
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                std::nullopt
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::No,
                DetectionMissingOnFrameMissingReason::Hidden
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::No,
                DetectionMissingOnFrameMissingReason::Missing
            )}
          },
          {// Result from user 2
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_2,
           {DetectionMissingOnFrame::TaskInput(SOURCE_1_1, bbox, SOURCE_1_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_2_1, bbox, SOURCE_2_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_3_1, bbox, SOURCE_3_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_4_1, bbox, SOURCE_4_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_5_1, bbox, SOURCE_5_2)},
           {
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                std::nullopt
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                std::nullopt
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::NotLoaded,
                std::nullopt
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::No,
                DetectionMissingOnFrameMissingReason::Hidden
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::No,
                DetectionMissingOnFrameMissingReason::Hidden
            )}
          },
          {// Result from user 3
           TS_1,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_3,
           {DetectionMissingOnFrame::TaskInput(SOURCE_1_1, bbox, SOURCE_1_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_2_1, bbox, SOURCE_2_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_3_1, bbox, SOURCE_3_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_4_1, bbox, SOURCE_4_2),
            DetectionMissingOnFrame::TaskInput(SOURCE_5_1, bbox, SOURCE_5_2)},
           {
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                std::nullopt
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::No,
                DetectionMissingOnFrameMissingReason::Hidden
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::No,
                DetectionMissingOnFrameMissingReason::Hidden
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                std::nullopt
            ),
            DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::No,
                DetectionMissingOnFrameMissingReason::PlaceIsNotVisible
            )}
        }}},
        {TS_2,
         {{TS_2,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_1,
           {DetectionMissingOnFrame::TaskInput(SOURCE_6_1, bbox, SOURCE_6_2)},
           {DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                DetectionMissingOnFrameMissingReason::Hidden
            )}
          },
          {TS_2,
           "unused",
           io::AssignmentStatus::Submitted,
           USER_2,
           {DetectionMissingOnFrame::TaskInput(SOURCE_6_1, bbox, SOURCE_6_2)},
           {DetectionMissingOnFrame::TaskOutput(
                DetectionMissingOnFrameIsVisible::Yes,
                DetectionMissingOnFrameMissingReason::Hidden
            )}
        }}}};

    auto tsResults = mergeTasksResults<DetectionMissingOnFrame>(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,
        DetectionMissingOnFrame::TaskOutput(
            DetectionMissingOnFrameIsVisible::Yes,
            std::nullopt
        )
    );

    EXPECT_EQ(
        taskResults[1].output,
        DetectionMissingOnFrame::TaskOutput(
            DetectionMissingOnFrameIsVisible::Yes,
            std::nullopt
        )
    );
    EXPECT_EQ(
        taskResults[2].output,
        DetectionMissingOnFrame::TaskOutput(
            DetectionMissingOnFrameIsVisible::Unknown,
            std::nullopt
        )
    );
    EXPECT_EQ(
        taskResults[3].output,
        DetectionMissingOnFrame::TaskOutput(
            DetectionMissingOnFrameIsVisible::No,
            DetectionMissingOnFrameMissingReason::Hidden
        )
    );
    EXPECT_EQ(
        taskResults[4].output,
        DetectionMissingOnFrame::TaskOutput(
            DetectionMissingOnFrameIsVisible::No,
            DetectionMissingOnFrameMissingReason::Unknown
        )
    );
}

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