// SPDX-FileCopyrightText: 2024 g10 Code GmbH
// SPDX-FileContributor: Carl Schwan <carl@carlschwan.eu>
// SPDX-License-Identifier: GPL-3.0-or-later

#include "job/directoryreencryptjob.h"
#include "job/filedecryptjob.h"
#include "job/fileencryptjob.h"
#include "job/filereencryptjob.h"
#include "models/storemodel.h"
#include "rootfoldersmanager.h"
#include <QSignalSpy>
#include <QTest>

class TestReencryptJob : public QObject
{
    Q_OBJECT

private Q_SLOTS:
    void reencryptFile();
    void reencryptDirectory();
};

void TestReencryptJob::reencryptFile()
{
    const QByteArray content("mypassword\nlogin: myusername\nurl: mywebsite.com\nmy notes\n");
    const QString filePath = QString::fromLatin1(DATA_DIR) + QStringLiteral("/myotherwebsite.gpg");
    const QList<QByteArray> recipients = {"14B79E26050467AA"};

    // Write
    {
        auto encryptJob = new FileEncryptJob(filePath, content, recipients);
        QSignalSpy writeSpy(encryptJob, &FileEncryptJob::result);
        encryptJob->start();
        writeSpy.wait();
        QCOMPARE(writeSpy.count(), 1);
        QCOMPARE(encryptJob->error(), KJob::NoError);
    }

    const QList<QByteArray> newRecipients = {"14B79E26050467AA", "FC4FAB94C727D4BB"};

    // Reencrypt
    {
        auto encryptJob = new FileReencryptJob(filePath, newRecipients);
        QSignalSpy writeSpy(encryptJob, &FileEncryptJob::result);
        encryptJob->start();
        writeSpy.wait();
        QCOMPARE(writeSpy.count(), 1);
        QCOMPARE(encryptJob->error(), KJob::NoError);
    }

    // Read again
    {
        auto decryptJob = new FileDecryptJob(filePath);
        QSignalSpy spy(decryptJob, &FileDecryptJob::result);
        decryptJob->start();
        spy.wait();
        QCOMPARE(decryptJob->content().toUtf8(), content);
        QCOMPARE(decryptJob->recipients(), newRecipients);
    }
}

void TestReencryptJob::reencryptDirectory()
{
    const QByteArray content("mypassword\nlogin: myusername\nurl: mywebsite.com\nmy notes\n");
    const QStringList filePaths = {QString::fromLatin1(DATA_DIR) + QStringLiteral("/dir/myotherwebsite.gpg"),
                                   QString::fromLatin1(DATA_DIR) + QStringLiteral("/dir/myotherwebsite2.gpg")};
    const QString gpgIdPath = QString::fromLatin1(DATA_DIR) + QStringLiteral("/dir/.gpg-id");
    StoreModel storeModel;
    RootFoldersManager rootFoldersManager;
    rootFoldersManager.addRootFolder(QStringLiteral("test"), QString::fromLatin1(DATA_DIR));
    storeModel.setRootFoldersManager(&rootFoldersManager);

    const QList<QByteArray> recipients = {"14B79E26050467AA"};
    {
        QFile file(gpgIdPath);
        auto ok = file.open(QIODevice::WriteOnly | QIODevice::Text);
        QVERIFY(ok);
        ok = file.write(recipients.join('\n'));
    }

    for (const auto &filePath : filePaths) {
        auto encryptJob = new FileEncryptJob(filePath, content, recipients);
        QSignalSpy writeSpy(encryptJob, &FileEncryptJob::result);
        encryptJob->start();
        writeSpy.wait();
        QCOMPARE(writeSpy.count(), 1);
        QCOMPARE(encryptJob->error(), KJob::NoError);
    }

    const QList<QByteArray> newRecipients = {"14B79E26050467AA", "FC4FAB94C727D4BB"};

    // Reencrypt
    {
        auto encryptJob = new DirectoryReencryptJob(storeModel, newRecipients, QString::fromLatin1(DATA_DIR) + QStringLiteral("/dir/"));
        QSignalSpy writeSpy(encryptJob, &DirectoryReencryptJob::result);
        encryptJob->start();
        writeSpy.wait();
        QCOMPARE(writeSpy.count(), 1);
        QCOMPARE(encryptJob->error(), KJob::NoError);
    }

    // check .gpg-id content
    {
        QFile file(gpgIdPath);
        auto ok = file.open(QIODevice::ReadOnly | QIODevice::Text);
        QVERIFY(ok);
        const auto recipientsInFile = file.readAll();
        QCOMPARE(newRecipients.join('\n'), recipientsInFile);
    }

    // Read again
    for (const auto &filePath : filePaths) {
        auto decryptJob = new FileDecryptJob(filePath);
        QSignalSpy spy(decryptJob, &FileDecryptJob::result);
        decryptJob->start();
        spy.wait();
        QCOMPARE(decryptJob->content().toUtf8(), content);
        QCOMPARE(decryptJob->recipients(), newRecipients);
    }

    {
        QFile file(gpgIdPath);
        auto ok = file.open(QIODevice::WriteOnly);
        QVERIFY(ok);
        ok = file.write(recipients.join('\n'));
    }
}

QTEST_MAIN(TestReencryptJob)
#include "tst_reencryptjob.moc"
