#include <maps/wikimap/mapspro/services/tasks_realtime/src/user_edits_metrics/lib/stat_utils/st_agent.h>
#include <maps/wikimap/mapspro/services/tasks_realtime/src/user_edits_metrics/lib/stat_utils/st_tag.h>

#include <maps/libs/http/include/test_utils.h>
#include <maps/libs/json/include/value.h>
#include <maps/libs/st/issue_impl.h>
#include <maps/libs/st/comment_impl.h>
#include <maps/libs/st/issue_collection_impl.h>
#include <maps/libs/st/http_client.h>
#include <maps/libs/log8/include/log8.h>

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

namespace maps::wiki::user_edits_metrics::tests {

using namespace std::string_literals;

const std::string& getJsonIssueStr() {
    static const std::string jsonIssueStr = NResource::Find("st_agent_test.json");
    return jsonIssueStr;
}

const auto& getJsonIssue() {
    static const auto jsonIssue = json::Value::fromString(getJsonIssueStr());
    return jsonIssue;
}

Y_UNIT_TEST_SUITE(st_agent_test)
{

Y_UNIT_TEST(test_st_tag)
{
    const auto TAG_PREFIX = "last_update_by_user_edits_metrics_"s;
    const auto time = chrono::parseIsoDate("2021-01-23");
    UNIT_ASSERT_EQUAL(timeToTag(time), TAG_PREFIX + "2021-01-23"s);
    const std::unordered_set<std::string> tags = {
        "some tag"s,
        TAG_PREFIX + "2021-01-23"s,
        TAG_PREFIX,
        TAG_PREFIX + "2010-02-23"s
    };
    UNIT_ASSERT_EQUAL(tagsToDate(tags).time_since_epoch().count(), time.time_since_epoch().count());
    UNIT_ASSERT(!tagFormatCorrect("Random tag"));
    UNIT_ASSERT(tagFormatCorrect(TAG_PREFIX));
    UNIT_ASSERT(tagFormatCorrect(TAG_PREFIX + "2021-01-23"s));
}

Y_UNIT_TEST(test_create_ticket)
{
    const std::unordered_set<std::string> followers = {"aleksbalashov, alexbobkov"};
    auto mockHandle = maps::http::addMock(
        "https://st-api.yandex-team.ru/v2/issues",
        [&](const maps::http::MockRequest& request) {
            const auto jsonRequest = json::Value::fromString(request.body);
            UNIT_ASSERT_VALUES_EQUAL(jsonRequest["queue"].as<std::string>(), "TEST_QUEUE_KEY");
            UNIT_ASSERT_VALUES_EQUAL(jsonRequest["description"].as<std::string>(), "Some description");
            UNIT_ASSERT_VALUES_EQUAL(jsonRequest["summary"].as<std::string>(), "Some summary");
            for (const auto& follower: jsonRequest["followers"]) {
                UNIT_ASSERT(followers.count(follower.toString()) > 0);
            }
            return maps::http::MockResponse(getJsonIssueStr());
        }
    );
    StAgent stAgent("TEST_QUEUE_KEY", "any_token");
    const auto issue = stAgent.createIssue("Some summary", "Some description", followers);

    UNIT_ASSERT_VALUES_EQUAL(issue.key(), getJsonIssue()["key"].as<std::string>());
    UNIT_ASSERT_VALUES_EQUAL(issue.summary(), getJsonIssue()["summary"].as<std::string>());
    UNIT_ASSERT_VALUES_EQUAL(issue.description(), getJsonIssue()["description"].as<std::string>());
}

Y_UNIT_TEST(test_find_opened_ticket)
{
    auto mockHandle = maps::http::addMock(
        "https://st-api.yandex-team.ru/v2/issues",
        [&](const maps::http::MockRequest& request) {
            const std::string expectedUrl(
                "https://st-api.yandex-team.ru/v2/issues?"
                "query=Queue%3A%20TEST_QUEUE_KEY%20and%20Status%3A%20Open%20and%20"
                "Summary%3A%20%22Some%20summary%22%20%22Sort%20By%22%3A%20Created%20DESC&scrollType=sorted"
            );
            UNIT_ASSERT_VALUES_EQUAL(request.url.toString(), expectedUrl);

            auto response = maps::http::MockResponse("["s + getJsonIssueStr() + "]"s);
            response.headers["X-Total-Count"] = "1";
            return response;
        }
    );
    StAgent stAgent("TEST_QUEUE_KEY", "any_token");
    const auto issue = stAgent.findOpenedIssue("Some summary");
    UNIT_ASSERT_VALUES_EQUAL(issue->summary(), getJsonIssue()["summary"].as<std::string>());
    UNIT_ASSERT_VALUES_EQUAL(issue->key(), getJsonIssue()["key"].as<std::string>());
}

Y_UNIT_TEST(test_update_issue)
{
    const std::string comments = "comm  ent1\ncomment2";
    std::string requestComments;

    const std::string urlBase = "https://st-api.yandex-team.ru/v2/issues/";
    auto mockHandle1 = maps::http::addMock(
        urlBase + getJsonIssue()["key"].as<std::string>(),
        [&](const maps::http::MockRequest& request) {
            const auto jsonRequest = json::Value::fromString(request.body);

            UNIT_ASSERT_VALUES_EQUAL(
                jsonRequest["tags"]["add"].begin()->as<std::string>(),
                timeToTag(chrono::parseIsoDate("2021-02-24"))
            );
            UNIT_ASSERT_VALUES_EQUAL(
                jsonRequest["tags"]["remove"].begin()->as<std::string>(),
                timeToTag(chrono::parseIsoDate("2021-02-23"))
            );
            return maps::http::MockResponse(getJsonIssueStr());
        }
    );
    auto mockHandle2 = maps::http::addMock(
        urlBase + getJsonIssue()["key"].as<std::string>() + "/comments",
        [&](const maps::http::MockRequest& request) {
            const auto jsonRequest = json::Value::fromString(request.body);
            requestComments = jsonRequest["text"].as<std::string>();
            return maps::http::MockResponse(getJsonIssueStr());
        }
    );
    StAgent stAgent("TEST_QUEUE_KEY", "any_token");
    const auto issue = PImplFactory::create<st::Issue>(getJsonIssue());
    stAgent.updateIssue(issue, comments, maps::chrono::parseIsoDate("2021-02-24"));
    UNIT_ASSERT_VALUES_EQUAL(comments, requestComments);
}

} // Y_UNIT_TEST_SUITE

} // namespace maps::wiki::user_edits_metrics::tests
