// 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);
    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);
        }
    }
    if (keys.empty()) {
        setError(EncryptionError);
        setErrorText(i18n("Could not read encryption key to use, .gpg-id file missing or invalid."));
        emitResult();
        return;
    }

    connect(job, &QGpgME::EncryptJob::result, this, [this](auto &&result, const QByteArray &ciphertext, const QString &log, auto &&auditResult) {
        Q_UNUSED(log);
        Q_UNUSED(auditResult);

        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();
    });
    job->start(keys, m_content);
}
