// SPDX-FileCopyrightText: 2024 g10 code GmbH
// SPDX-Contributor: Carl Schwan <carl.schwan@gnupg.com>
// SPDX-License-Identifier: GPL-2.0-or-later

#include "../editor/composerviewbase.h"
#include "../editor/part/textpart.h"
#include "../editor/recipientseditor.h"
#include "../editor/richtextcomposerng.h"
#include "../messagedispatcher.h"
#include <QObject>
#include <QSignalSpy>
#include <QTest>
#include <Sonnet/DictionaryComboBox>
#include <TextCustomEditor/RichTextEditorWidget>

using namespace Qt::StringLiterals;

static QByteArray readMailFromFile(const QString &mailFile)
{
    QFile file(QLatin1StringView(DATA_DIR) + QLatin1Char('/') + mailFile);
    file.open(QIODevice::ReadOnly);
    Q_ASSERT(file.isOpen());
    return file.readAll();
}

class DummMessageDispatcher : public MessageDispatcher
{
    Q_OBJECT
public:
    void dispatch(const KMime::Message::Ptr &message, const QString &from, const QString &mailId) override
    {
        mMessages.emplace_back(message, from, mailId);
        Q_EMIT sentSuccessfully();
    }

    struct Message {
        KMime::Message::Ptr message;
        QString from;
        QString mailId;
    };
    std::vector<Message> mMessages;
};

class ComposerViewBaseTest : public QObject
{
    Q_OBJECT

private Q_SLOTS:
    void init()
    {
        mComposerBase = std::make_unique<MessageComposer::ComposerViewBase>();
        mComposerBase->setRecipientsEditor(&mRecipientsEditor);
        auto richTextComposer = new MessageComposer::RichTextComposerNg(nullptr);
        mComposerBase->setEditor(richTextComposer);
        mComposerBase->setMessageDispatcher(&mMessageDispatcher);
        mMessageDispatcher.mMessages.clear();
        mComposerBase->setDictionary(&mDictionaryComboBox);
    }

    void testSetMessage()
    {
        KMime::Message::Ptr message(new KMime::Message);
        message->setContent(KMime::CRLFtoLF(readMailFromFile(u"draft.mbox"_s)));
        message->parse();

        mComposerBase->setMessage(message);
        mComposerBase->setFrom(u"carl.from@carlschwan.eu"_s);

        QCOMPARE(mComposerBase->to(), QLatin1StringView("carl.to@carlschwan.eu"));
        QCOMPARE(mComposerBase->cc(), QLatin1StringView("carl.cc@carlschwan.eu"));
        QCOMPARE(mComposerBase->bcc(), QLatin1StringView("carl.bcc@carlschwan.eu"));
        QCOMPARE(mComposerBase->from(), QLatin1StringView("carl.from@carlschwan.eu"));
        QCOMPARE(mComposerBase->subject(), QLatin1StringView("Draft"));

        auto textPart = new MessageComposer::TextPart();
        mComposerBase->editor()->fillComposerTextPart(textPart);
        QCOMPARE(textPart->cleanPlainText(), QLatin1StringView("Draft content"));
    }

    void testSetMessageTooManyRecipient()
    {
        KMime::Message::Ptr message(new KMime::Message);
        message->setContent(KMime::CRLFtoLF(readMailFromFile(u"plaintexttoomanyrecipient.mbox"_s)));
        message->parse();

        QSignalSpy tooManySignal(mComposerBase.get(), &MessageComposer::ComposerViewBase::tooManyRecipient);
        mComposerBase->setMessage(message);
        QCOMPARE(tooManySignal.count(), 1);
    }

    void testSetMessageHtml()
    {
        KMime::Message::Ptr message(new KMime::Message);
        message->setContent(KMime::CRLFtoLF(readMailFromFile(u"html.mbox"_s)));
        message->parse();

        QSignalSpy enableHtmlSignal(mComposerBase.get(), &MessageComposer::ComposerViewBase::enableHtml);
        mComposerBase->setMessage(message);
        QCOMPARE(enableHtmlSignal.count(), 1);

        auto textPart = new MessageComposer::TextPart();
        mComposerBase->editor()->fillComposerTextPart(textPart);
        QCOMPARE(textPart->cleanPlainText(), QLatin1StringView("*SOME* HTML text. \n"));
        QVERIFY(textPart->isHtmlUsed());
        QCOMPARE(textPart->cleanHtml(),
                 QLatin1StringView(
                     "<html>\n<head>\n<meta http-equiv=\"content-type\" content=\"text/html; charset=UTF-8\">\n</head>\n<body><p "
                     "style=\"margin-top:0;margin-bottom:0;margin-left:0;margin-right:0;\"><strong>SOME</strong>&nbsp;HTML text. </p>\n</body>\n</html>"));
    }

    void testSendMessageNotEncryptedPlainText()
    {
        mComposerBase->setFrom(u"from@example.com"_s);
        mComposerBase->setSubject(u"Subject"_s);
        mComposerBase->setCryptoOptions(false, false, {});
        mComposerBase->editor()->setText(u"Content"_s);
        mComposerBase->send();

        QCOMPARE(mMessageDispatcher.mMessages.size(), 1);
        QCOMPARE(mMessageDispatcher.mMessages[0].from, u"from@example.com"_s);
        const auto message = mMessageDispatcher.mMessages[0].message;

        QCOMPARE(message->header<KMime::Headers::Subject>()->asUnicodeString(), u"Subject"_s);
        QCOMPARE(message->header<KMime::Headers::From>()->asUnicodeString(), u"from@example.com"_s);
        QCOMPARE(message->header<KMime::Headers::MIMEVersion>()->asUnicodeString(), u"1.0"_s);
        QCOMPARE(message->header<KMime::Headers::ContentTransferEncoding>()->encoding(), KMime::Headers::CE7Bit);
        QVERIFY(message->header<KMime::Headers::ContentType>()->isPlainText());

        QCOMPARE(message->decodedContent(), "Content");
    }

    void testSendMessageNotEncryptedRichText()
    {
        mComposerBase->setFrom(u"from@example.com"_s);
        mComposerBase->setSubject(u"Subject"_s);
        mComposerBase->setCryptoOptions(false, false, {});
        mComposerBase->editor()->activateRichText();
        mComposerBase->editor()->setText(u"<p style=\"color:red\">Content</p>"_s);
        mComposerBase->send();

        QCOMPARE(mMessageDispatcher.mMessages.size(), 1);
        QCOMPARE(mMessageDispatcher.mMessages[0].from, u"from@example.com"_s);
        const auto message = mMessageDispatcher.mMessages[0].message;

        QCOMPARE(message->header<KMime::Headers::Subject>()->asUnicodeString(), u"Subject"_s);
        QCOMPARE(message->header<KMime::Headers::From>()->asUnicodeString(), u"from@example.com"_s);
        QCOMPARE(message->header<KMime::Headers::MIMEVersion>()->asUnicodeString(), u"1.0"_s);
        QCOMPARE(message->header<KMime::Headers::ContentTransferEncoding>()->encoding(), KMime::Headers::CE7Bit);

        qWarning().noquote() << message->encodedContent();
        QVERIFY(!message->header<KMime::Headers::ContentType>()->isPlainText());

        const auto textPart = message->contents()[0];
        QCOMPARE(textPart->decodedContent(), "Content\n");

        const auto htmlPart = message->contents()[1];
        QCOMPARE(htmlPart->decodedContent(), R"(<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
</head>
<body><p style="margin-top:12;margin-bottom:12;margin-left:0;margin-right:0;"><span style="color:#ff0000;">Content</span></p>
</body>
</html>)");
    }

private:
    std::unique_ptr<MessageComposer::ComposerViewBase> mComposerBase;
    DummMessageDispatcher mMessageDispatcher;
    RecipientsEditor mRecipientsEditor;
    Sonnet::DictionaryComboBox mDictionaryComboBox;
};

QTEST_MAIN(ComposerViewBaseTest)
#include "composerviewbasetest.moc"