#include <maps/wikimap/mapspro/services/tasks_feedback/src/releases_notification_worker/lib/email_params_rendering.h>
#include <maps/libs/locale/include/find_helpers.h>
#include <maps/libs/http/include/http.h>
#include <maps/wikimap/mapspro/libs/sender/include/config.h>

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

#include <iostream>

namespace maps::wiki::releases_notification::test {

namespace {

const std::string SENDER_CONFIG = ArcadiaSourceRoot() +
    "/maps/wikimap/mapspro/services/tasks_feedback/src/releases_notification_worker/tests/sender.json";

sender::ConstantParams loadSenderConstants()
{
    return sender::ConstantParams::fromJson(json::Value::fromFile(SENDER_CONFIG));
}


void checkMapsEqual(
    const std::map<std::string, std::string>& left,
    const std::map<std::string, std::string>& right)
{
    for (const auto& [leftKey, leftVal] : left) {
        UNIT_ASSERT_C(right.count(leftKey) > 0, "key '" << leftKey << "' is not found in right map");
        UNIT_ASSERT_STRINGS_EQUAL(leftVal, right.at(leftKey));
    }
    for (const auto& [rightKey, rightVal]: right) {
        UNIT_ASSERT_C(left.count(rightKey) > 0, "key '" << rightKey << "' is not found in left map");
        UNIT_ASSERT_STRINGS_EQUAL(rightVal, left.at(rightKey));
    }
}

} // namespace

Y_UNIT_TEST_SUITE(rendering) {

Y_UNIT_TEST(simple_date_from_time_point)
{
    {
        auto dt = SimpleDate::fromTimePoint(
            chrono::parseSqlDateTime("2015-06-16 15:25:21.662649+03"),
            locale::Locale(locale::Lang::Ru));
        UNIT_ASSERT_STRINGS_EQUAL(dt.day, "16");
        UNIT_ASSERT_STRINGS_EQUAL(dt.month, "июня");
        UNIT_ASSERT_STRINGS_EQUAL(dt.year, "2015");
    }
    {
        auto dt = SimpleDate::fromTimePoint(
            chrono::parseSqlDateTime("2017-09-15 15:25:21.662649+03"),
            locale::Locale(locale::Lang::Hy));
        UNIT_ASSERT_STRINGS_EQUAL(dt.day, "15");
        UNIT_ASSERT_STRINGS_EQUAL(dt.month, "Սեպտեմբեր");
        UNIT_ASSERT_STRINGS_EQUAL(dt.year, "2017");
    }
}

Y_UNIT_TEST(sat_template_params)
{
    auto senderConstants = loadSenderConstants();

    TaskParams taskParams(
        "https://yandex.ru/blog_url",
        Mode::Real,
        ReleaseType::Sat,
        0,
        {});

    std::unique_ptr<EmptyParams> typeSpecificParams(new EmptyParams);

    {
        UserInfo ruUserInfo{1, "petya@yandex.ru", locale::Locale(locale::Lang::Ru), std::string("Петя")};

        auto paramsMap = renderEmailParams(
            *typeSpecificParams,
            ruUserInfo,
            senderConstants,
            taskParams).data();

        std::map<std::string, std::string> expectedParams{
            {"blog_url", "yandex.ru/blog_url"},
            {"club_url", "yandex.ru/blog/narod-karta/"},
            {"maps_url", "yandex.ru/maps/"},
            {"nmaps_url", "n.maps.yandex.ru/"},
            {"feedback_url", "yandex.ru/support/nmaps/troubleshooting/fb_nmaps.xml"},
            {"unsubscribe_url", "n.maps.yandex.ru/#!/users/me/edit"},
            {"username", "Петя"}
        };

        checkMapsEqual(expectedParams, paramsMap);
    }

    {
        UserInfo enUserInfo{2, "john@yandex.com", locale::Locale(locale::Lang::En), std::string("John")};

        auto paramsMap = renderEmailParams(
            *typeSpecificParams,
            enUserInfo,
            senderConstants,
            taskParams).data();

        std::map<std::string, std::string> expectedParams{
            {"blog_url", "yandex.ru/blog_url"},
            {"club_url", "yandex.ru/blog/narod-karta/"},
            {"maps_url", "yandex.com/maps/"},
            {"nmaps_url", "mapeditor.yandex.com/"},
            {"feedback_url", "yandex.com/support/mapeditor/"},
            {"unsubscribe_url", "mapeditor.yandex.com/#!/users/me/edit"},
            {"username", "John"}
        };

        checkMapsEqual(expectedParams, paramsMap);
    }
}


Y_UNIT_TEST(vec_share_text_ru)
{
    auto check = [](size_t commitsCount, const std::string& expectedText) {
        auto senderConstants = loadSenderConstants();

        TaskParams taskParams(
            "https://yandex.ru/blog_url",
            Mode::Real,
            ReleaseType::Vec,
            0,
            {});

        std::unique_ptr<VecParams> typeSpecificParams(new VecParams(
            commitsCount,
            chrono::parseIsoDateTime("2017-01-02T03:04:05"),
            chrono::parseIsoDateTime("2017-02-02T03:04:05")
        ));

        UserInfo ruUserInfo{1, "petya@yandex.ru", locale::Locale(locale::Lang::Ru), std::string("Петя")};

        auto paramsMap = renderEmailParams(
            *typeSpecificParams,
            ruUserInfo,
            senderConstants,
            taskParams).data();

        UNIT_ASSERT_STRINGS_EQUAL(paramsMap["share_description_text"], http::urlEncode(expectedText));
    };

    check(0, "А я правок не делал");
    check(1, "Моя правка опубликована");
    check(2, "2 мои правки опубликованы");
    check(5, "5 моих правок опубликовано");
    check(10, "10 моих правок опубликовано");
    check(11, "11 моих правок опубликовано");
    check(20, "20 моих правок опубликовано");
    check(21, "21 моя правка опубликована");
    check(24, "24 мои правки опубликованы");
    check(36, "36 моих правок опубликовано");
    check(100, "100 моих правок опубликовано");
    check(101, "101 моя правка опубликована");
    check(103, "103 мои правки опубликованы");
    check(105, "105 моих правок опубликовано");
    check(113, "113 моих правок опубликовано");
}


Y_UNIT_TEST(vec_template_params)
{
    auto senderConstants = loadSenderConstants();

    TaskParams taskParams(
        "https://yandex.ru/blog_url",
        Mode::Real,
        ReleaseType::Vec,
        0,
        {});

    std::unique_ptr<VecParams> typeSpecificParams(new VecParams(
        14,
        chrono::parseIsoDateTime("2017-01-02T03:04:05"),
        chrono::parseIsoDateTime("2017-02-02T03:04:05")
    ));

    {
        UserInfo ruUserInfo{1, "petya@yandex.ru", locale::Locale(locale::Lang::Ru), std::string("Петя")};

        auto paramsMap = renderEmailParams(
            *typeSpecificParams,
            ruUserInfo,
            senderConstants,
            taskParams).data();

        std::map<std::string, std::string> expectedParams{
            {"blog_url", "yandex.ru/blog_url"},
            {"club_url", "yandex.ru/blog/narod-karta/"},
            {"corrections_count", "14"},
            {"maps_url", "yandex.ru/maps/"},
            {"nmaps_url", "n.maps.yandex.ru/"},
            {"feedback_url", "yandex.ru/support/nmaps/troubleshooting/fb_nmaps.xml"},
            {"share_description_text", http::urlEncode("14 моих правок опубликовано")},
            {"share_title_text", http::urlEncode("Яндекс.Карты обновились.")},
            {"since_day", "2"},
            {"since_month", "января"},
            {"since_year", "2017"},
            {"till_day", "2"},
            {"till_month", "февраля"},
            {"till_year", "2017"},
            {"unsubscribe_url", "n.maps.yandex.ru/#!/users/me/edit"},
            {"username", "Петя"},
        };

        checkMapsEqual(expectedParams, paramsMap);
    }

    {
        UserInfo hyUserInfo{2, "arthur@yandex.ru", locale::Locale(locale::Lang::Hy), std::string("Артур")};

        auto paramsMap = renderEmailParams(
            *typeSpecificParams,
            hyUserInfo,
            senderConstants,
            taskParams).data();

        std::map<std::string, std::string> expectedParams{
            {"blog_url", "yandex.ru/blog_url"},
            {"club_url", "yandex.ru/blog/narod-karta/"},
            {"corrections_count", "14"},
            {"maps_url", "yandex.com/maps/"},
            {"nmaps_url", "mapeditor.yandex.com/"},
            {"feedback_url", "yandex.com/support/mapeditor-hy/fb.html"},
            // share texts are not used in hy template
            {"share_description_text", http::urlEncode("14 моих правок опубликовано")},
            {"share_title_text", http::urlEncode("Яндекс.Карты обновились.")},
            {"since_day", "2"},
            {"since_month", "Հունվար"},
            {"since_year", "2017"},
            {"till_day", "2"},
            {"till_month", "Փետրվար"},
            {"till_year", "2017"},
            {"unsubscribe_url", "mapeditor.yandex.com/#!/users/me/edit"},
            {"username", "Артур"},
        };

        checkMapsEqual(expectedParams, paramsMap);
    }


    {
        UserInfo noNameFrUserInfo{3, "jan@yandex.com", locale::Locale(locale::Lang::Fr), std::nullopt};

        auto paramsMap = renderEmailParams(
            *typeSpecificParams,
            noNameFrUserInfo,
            senderConstants,
            taskParams).data();

        std::map<std::string, std::string> expectedParams{
            {"blog_url", "yandex.ru/blog_url"},
            {"club_url", "yandex.ru/blog/narod-karta/"},
            {"corrections_count", "14"},
            {"maps_url", "yandex.com/maps/"},
            {"nmaps_url", "mapeditor.yandex.com/"},
            {"feedback_url", "yandex.com/support/mapeditor-fr/"},
            // share texts are not used in fr template
            {"share_description_text", http::urlEncode("14 моих правок опубликовано")},
            {"share_title_text", http::urlEncode("Яндекс.Карты обновились.")},
            {"since_day", "2"},
            {"since_month", "Janvier"},
            {"since_year", "2017"},
            {"till_day", "2"},
            {"till_month", "Février"},
            {"till_year", "2017"},
            {"unsubscribe_url", "mapeditor.yandex.com/#!/users/me/edit"}
        };

        checkMapsEqual(expectedParams, paramsMap);
    }

}

} // rendering tests suite

} // maps::wiki::releases_notification::test
