#pragma once

/**
 * Sender HTTP API client implementation
 * https://github.yandex-team.ru/sendr/sendr/blob/master/docs/transaction-api.md
 */

#include "config.h"
#include "defs.h"
#include <maps/libs/enum_io/include/enum_io_fwd.h>
#include <maps/libs/http/include/http.h>
#include <maps/libs/common/include/retry.h>

namespace maps::wiki::sender {

class EmailTemplateParams;

enum class Result
{
    Sent,
    NoEmail,
    Failed
};

DECLARE_ENUM_IO(Result);


class BaseGateway
{
protected:
    BaseGateway(
        std::string endPoint,
        Credentials credentials,
        const maps::common::RetryPolicy& retryPolicy);

public:
    virtual Result sendToEmail(
        const CampaignSlug& campaign,
        const std::string& toEmail,
        const EmailTemplateParams& templateParams) const = 0;

    virtual Result sendToYandexPuid(
        const CampaignSlug& campaign,
        uint64_t toYandexPuid,
        const EmailTemplateParams& templateParams) const = 0;

    virtual Result send(
        const CampaignSlug& campaign,
        const std::string& requestBody) const = 0;

    virtual ~BaseGateway() = default;

protected:
    http::URL createUrlWithoutParams(const CampaignSlug& campaign) const;

    std::string endPoint_;
    Credentials credentials_;
    maps::common::RetryPolicy retryPolicy_;
};


class Gateway : public BaseGateway
{
public:
    Gateway(
        std::string endPoint,
        Credentials credentials,
        const maps::common::RetryPolicy& retryPolicy)
    : BaseGateway(endPoint, credentials, retryPolicy) {}

    Result sendToEmail(
        const CampaignSlug& campaign,
        const std::string& toEmail,
        const EmailTemplateParams& templateParams) const;

    Result sendToYandexPuid(
        const CampaignSlug& campaign,
        uint64_t toYandexPuid,
        const EmailTemplateParams& templateParams) const;

    Result send(
        const CampaignSlug& campaign,
        const std::string& requestBody) const;

private:
    Result sendToUrl(const http::URL& url, const std::string& requestBody) const;
};

// Stub for doing nothing
// Useful to make dry run mode in dependent tools
class DryGateway: public BaseGateway
{
public:
    DryGateway(
        std::string endPoint,
        Credentials credentials,
        const maps::common::RetryPolicy& retryPolicy)
    : BaseGateway(endPoint, credentials, retryPolicy) {}

    Result sendToEmail(
        const CampaignSlug& campaign,
        const std::string& toEmail,
        const EmailTemplateParams& templateParams) const override;

    Result sendToYandexPuid(
        const CampaignSlug& campaign,
        uint64_t toYandexPuid,
        const EmailTemplateParams& templateParams) const override;

    Result send(
        const CampaignSlug& campaign,
        const std::string& requestBody) const override;
};

} // namespace maps::wiki::sender
