#pragma once

#include "tests_common.h"

#include <maps/wikimap/mapspro/services/editor/src/common.h>
#include <yandex/maps/wiki/social/moderation.h>
#include <yandex/maps/wiki/social/task.h>

#include <library/cpp/testing/unittest/registar.h>

#include <fmt/format.h>

#include <memory>
#include <optional>
#include <utility>


#define WIKI_ASSERT_TASK_UNRESOLVED(task) \
    UNIT_ASSERT_C(!(task).isResolved(), "Task has resolve resolution");


#define WIKI_ASSERT_COMMIT_HAS_NO_TASK(commitId)        \
    do {                                                \
        UNIT_ASSERT_EXCEPTION_CONTAINS(                 \
            getTask(commitId),                          \
            maps::wiki::LogicException,                 \
            "Not existing moderation task by commit id" \
        );                                              \
    } while (false)


#define WIKI_ASSERT_COMMIT_TASK_UNRESOLVED(commitId)    \
    do {                                                \
        const auto task = getTask(commitId);            \
        UNIT_ASSERT(task);                              \
        WIKI_ASSERT_TASK_UNRESOLVED(*task);             \
    } while (false)


#define WIKI_ASSERT_TASK_RESOLVED(task, resolvedBy, resolveResolution)                      \
    do {                                                                                    \
        UNIT_ASSERT_C((task).isResolved(), "Task has no resolve resolution");               \
        UNIT_ASSERT_VALUES_EQUAL_C(                                                         \
            resolvedBy, (task).resolved().uid(),                                            \
            fmt::format(                                                                    \
                "It is expected that the task is resolved by {} but it was resolved by {}", \
                resolvedBy, (task).resolved().uid()                                         \
            )                                                                               \
        );                                                                                  \
        UNIT_ASSERT_VALUES_EQUAL(                                                           \
            (task).resolved().resolution(),                                                 \
            social::ResolveResolution::resolveResolution                                    \
        );                                                                                  \
        UNIT_ASSERT_C(!(task).isClosed(), "Task has close resolution");                     \
    } while (false)


#define WIKI_ASSERT_COMMIT_TASK_RESOLVED(commitId, resolvedBy, resolveResolution) \
    do {                                                                          \
        const auto task = getTask(commitId);                                      \
        UNIT_ASSERT(task);                                                        \
        WIKI_ASSERT_TASK_RESOLVED(*task, resolvedBy, resolveResolution);          \
    } while (false)


#define WIKI_ASSERT_TASK_CLOSED(task, resolvedBy, resolveResolution, closedBy, closeResolution) \
    do {                                                                                        \
        UNIT_ASSERT_C((task).isResolved(), "Task has no resolve resolution");                   \
        UNIT_ASSERT_VALUES_EQUAL_C(                                                             \
            resolvedBy, (task).resolved().uid(),                                                \
            fmt::format(                                                                        \
                "It is expected that the task is resolved by {} but it was resolved by {}",     \
                resolvedBy, (task).resolved().uid()                                             \
            )                                                                                   \
        );                                                                                      \
        UNIT_ASSERT_VALUES_EQUAL(                                                               \
            (task).resolved().resolution(),                                                     \
            social::ResolveResolution::resolveResolution                                        \
        );                                                                                      \
                                                                                                \
        UNIT_ASSERT_C((task).isClosed(), "Task has no close resolution");                       \
        UNIT_ASSERT_VALUES_EQUAL_C(                                                             \
            closedBy, (task).closed().uid(),                                                    \
            fmt::format(                                                                        \
                "It is expected that the task is closed by {} but it was closed by {}",         \
                closedBy, (task).closed().uid()                                                 \
            )                                                                                   \
        );                                                                                      \
        UNIT_ASSERT_VALUES_EQUAL(                                                               \
            (task).closed().resolution(),                                                       \
            social::CloseResolution::closeResolution                                            \
        );                                                                                      \
    } while (false)


#define WIKI_ASSERT_COMMIT_TASK_CLOSED(commitId, resolvedBy, resolveResolution, closedBy, closeResolution) \
    do {                                                                                                   \
        const auto task = getTask(commitId);                                                               \
        UNIT_ASSERT(task);                                                                                 \
        WIKI_ASSERT_TASK_CLOSED(*task, resolvedBy, resolveResolution, closedBy, closeResolution);          \
    } while (false)


namespace maps::wiki::tests {

std::unique_ptr<social::Task>
getTask(
    TCommitId commitId,
    TUid userId = TESTS_USER);

} // namespace maps::wiki::tests
