BareGit
#include <chrono>
#include <memory>
#include <string>

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <mw/http_client_mock.hpp>

#include "email_sender_mailjet.h"

TEST(MailjetEmailSenderTest, ConfiguresAndSendsSuccessfulRequest)
{
    auto session = std::make_unique<mw::HTTPSessionMock>();
    mw::HTTPSessionMock* mock = session.get();
    EXPECT_CALL(*mock, allowedProtocols("https"))
        .WillOnce(testing::Return(mw::E<void>{}));
    EXPECT_CALL(*mock, allowedRedirectProtocols("https"))
        .WillOnce(testing::Return(mw::E<void>{}));
    EXPECT_CALL(*mock, followRedirects(false));
    EXPECT_CALL(*mock, maxRedirections(0))
        .WillOnce(testing::Return(mw::E<void>{}));
    EXPECT_CALL(*mock, maxSize(64 * 1024))
        .WillOnce(testing::Return(mw::E<void>{}));
    EXPECT_CALL(*mock, connectionTimeout(std::chrono::seconds(5)))
        .WillOnce(testing::Return(mw::E<void>{}));
    EXPECT_CALL(*mock, transferTimeout(std::chrono::seconds(15)))
        .WillOnce(testing::Return(mw::E<void>{}));
    mw::HTTPResponse response(200, R"({"Messages":[{"Status":"success"}]})");
    EXPECT_CALL(*mock, post(testing::_))
        .WillOnce(testing::Invoke(
            [&response](const mw::HTTPRequest& request)
            {
                EXPECT_EQ(
                    request.url,
                    "https://api.mailjet.com/v3.1/send");
                EXPECT_EQ(
                    request.header.at("Content-Type"),
                    "application/json");
                EXPECT_EQ(
                    request.header.at("Authorization"),
                    "Basic YXBpOnNlY3JldA==");
                EXPECT_NE(request.request_data.find("person@example.com"),
                          std::string::npos);
                EXPECT_NE(request.request_data.find("confirm/token"),
                          std::string::npos);
                return mw::E<const mw::HTTPResponse*>(&response);
            }));
    MailjetEmailSender sender(
        std::move(session),
        "cards@example.com",
        "Card Collection",
        "api",
        "secret");
    ASSERT_TRUE(sender.configure());
    auto url = mw::URL::fromStr("https://cards.example/confirm/token");
    ASSERT_TRUE(url);

    auto sent = sender.send({
        "person@example.com",
        std::move(*url),
        std::chrono::system_clock::now() + std::chrono::minutes(10),
    });

    ASSERT_TRUE(sent) << sent.error().msg();
    EXPECT_TRUE(sender.usesGlobalQuota());
}

TEST(MailjetEmailSenderTest, RejectsUpstreamFailureAndInvalidJson)
{
    auto session = std::make_unique<mw::HTTPSessionMock>();
    mw::HTTPSessionMock* mock = session.get();
    mw::HTTPResponse response(502, "failure");
    EXPECT_CALL(*mock, post(testing::_))
        .WillOnce(testing::Return(
            mw::E<const mw::HTTPResponse*>(&response)));
    MailjetEmailSender sender(
        std::move(session), "a@example.com", "Cards", "api", "secret");
    auto url = mw::URL::fromStr("https://cards.example/confirm/token");
    ASSERT_TRUE(url);

    EXPECT_FALSE(sender.send({
        "person@example.com",
        std::move(*url),
        std::chrono::system_clock::now(),
    }));
}