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

#include "fileencryptjob.h"

#include <QSaveFile>

#include <KLocalizedString>
#include <Libkleo/Formatting>
#include <QGpgME/EncryptJob>
#include <QGpgME/Protocol>
#include <gpgme++/encryptionresult.h>

#include "gpgmehelpers.h"

FileEncryptJob::FileEncryptJob(const QString &filePath, const QByteArray &content, const QList<QByteArray> &recipientsKeys, QObject *parent)
    : KJob(parent)
    , m_filePath(filePath)
    , m_content(content)
    , m_recipientsKeys(recipientsKeys)
{
}

void FileEncryptJob::start()
{
    QGpgME::Protocol *protocol = QGpgME::openpgp();
    auto job = protocol->encryptJob();
    std::vector<GpgME::Key> keys;
    auto ctx = QGpgME::Job::context(job);

    QString errorString;
    for (const auto &keyId : std::as_const(m_recipientsKeys)) {
        GpgME::Error error;
        auto key = ctx->key(keyId.data(), error, false);
        if (!error && !key.isNull()) {
            keys.push_back(key);
        } else if (error) {
            errorString = i18nc("@info:status",
                                "Unable to find key for recipient with keyId \"%1\". Error: %2",
                                QString::fromUtf8(keyId),
                                Kleo::Formatting::errorAsString(error));
        } else {
            errorString = i18nc("@info:status", "Unable to find key for recipient with keyId \"%1\".", QString::fromUtf8(keyId));
        }
    }
    if (!errorString.isEmpty()) {
        setError(EncryptionError);
        setErrorText(errorString);
        emitResult();
        return;
    }

    connect(job,
            SIGNAL(result(GpgME::EncryptionResult, QByteArray, QString, GpgME::Error)),
            this,
            SLOT(slotEncryptedResult(GpgME::EncryptionResult, QByteArray, QString, GpgME::Error)));
    job->start(keys, m_content);
}

void FileEncryptJob::slotEncryptedResult(const GpgME::EncryptionResult &result,
                                         const QByteArray &ciphertext,
                                         const QString &auditLogAsHtml,
                                         const GpgME::Error &auditLogError)
{
    Q_UNUSED(auditLogAsHtml);
    Q_UNUSED(auditLogError);

    if (!isSuccess(result.error())) {
        setError(EncryptionError);
        setErrorText(Kleo::Formatting::errorAsString(result.error()));
        emitResult();
        return;
    }

    QSaveFile f(m_filePath);
    if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
        setError(PermissionError);
        setErrorText(f.errorString());
        emitResult();
        return;
    }

    f.write(ciphertext);
    if (f.error() != QFileDevice::NoError) {
        setError(PermissionError);
        setErrorText(f.errorString());
    }
    if (!f.commit()) {
        setError(PermissionError);
        setErrorText(f.errorString());
    }
    emitResult();
}
