#include "sender_mailing.h"
#include "consts.h"

namespace maps::wiki::notifications_sender {

using namespace std::literals::string_literals;

NotExistingCampaignError::NotExistingCampaignError(
    const ParsedMessage& message)
    : RuntimeError("Not existing campaign for message '" + toString(message) + "'")
{}

NotExistingCampaignError::NotExistingCampaignError(
    const ParsedMessage& message,
    const UserMailInfo& userInfo)
    : RuntimeError(
        "Not existing campaign for message '"s + toString(message) + "' and "s +
        "user locale '"s + userInfo.locale() + "'"s
      )
{}


SenderMailing::SenderMailing(const sender::CampaignsSlugs& campaigns) :
    campaigns_(campaigns)
{}

bool SenderMailing::isSuitableCampaignSlugExist(
    const ParsedMessage& message, const UserMailInfo& userInfo) const
{
    return getCampaignSlugNoThrow(message, userInfo).has_value();
}

sender::CampaignSlug SenderMailing::getCampaignSlug(
    const ParsedMessage& message, const UserMailInfo& userInfo) const
{
    auto campaignSlug = getCampaignSlugNoThrow(message, userInfo);
    if (campaignSlug) {
        return campaignSlug.value();
    } else {
        throw NotExistingCampaignError(message, userInfo);
    }
}

sender::EmailTemplateParams SenderMailing::getEmailParams(
    const ParsedMessage& message, const UserMailInfo& userInfo) const
{
    const auto& campaignName = getCampaignName(message);
    if (campaignName == CAMPAIGN_THANKS_FOR_NEWS_SUBSCRIBE) {
        return sender::EmailTemplateParams();
    } else if (campaignName == CAMPAIGN_ACHIEVE_EDITS_COUNT) {
        return sender::EmailTemplateParams::fromDict({
            {"achieve", std::to_string(message.args["editsCount"].as<size_t>())},
            {"lang", userInfo.locale()},
            {"username", userInfo.userName()}
        });
    } else if (campaignName == CAMPAIGN_ADDRESSES_SHOWS_COUNT) {
        return sender::EmailTemplateParams::fromDict({
            {"totalShowsCount", std::to_string(message.args["showsCount"].as<size_t>())},
            {"lang", userInfo.locale()},
            {"username", userInfo.userName()}
        });
    } else {
        return sender::EmailTemplateParams();
    }
}

const std::string& SenderMailing::getCampaignName(const ParsedMessage& message) const
{
    if (message.mailType == MAIL_TYPE_NEWS_SUBSCRIPTION_WELCOME) {
        return CAMPAIGN_THANKS_FOR_NEWS_SUBSCRIBE;
    } else if (message.mailType == MAIL_TYPE_ACHIEVE_EDITS_COUNT) {
        return CAMPAIGN_ACHIEVE_EDITS_COUNT;
    } else if (message.mailType == MAIL_TYPE_ADDRESSES_SHOWS_COUNT) {
        return CAMPAIGN_ADDRESSES_SHOWS_COUNT;
    }
    throw NotExistingCampaignError(message);
}

std::optional<sender::CampaignSlug> SenderMailing::getCampaignSlugNoThrow(
    const ParsedMessage& message, const UserMailInfo& userInfo) const
{
    const auto& campaignName = getCampaignName(message);
    if (campaignName == CAMPAIGN_ACHIEVE_EDITS_COUNT) {
        try {
            return campaigns_.getAchieveEdits().getCampaignSlug(
                message.args["editsCount"].as<size_t>(),
                userInfo.locale()
            );
        } catch (const sender::NotExistingCampaignAchieveEditsError&) {
            return std::nullopt;
        }
    }

    try {
        return campaigns_.getLocalizedByName(campaignName).slugs.getForLang(userInfo.locale());
    } catch (const sender::NotExistingCampaignError&) {
        return std::nullopt;
    } catch (const sender::NotExistingLangError&) {
        return std::nullopt;
    }
}

} // namespace maps::wiki::notifications_sender
