//
// Created by 张雪明 <zhangxueming@uniontech.com> on 2023/9/28.
//
#include "OSTreeWorkerThread.h"
#include <QtDBus/QtDBus>
#include <QDebug>
#include "utils/Utils.h"

static const QString DBUS_ATOMIC_UPGRADE_SERVICE = "org.deepin.AtomicUpgrade1";
static const QString DBUS_ATOMIC_UPGRADE_PATH = "/org/deepin/AtomicUpgrade1";
static const QString DBUS_ATOMIC_UPGRADE_INTERFACE = DBUS_ATOMIC_UPGRADE_SERVICE;
static const char *DBUS_ATOMIC_UPGRADE_RUNNING = "Running";
static const QString DBUS_ATOMIC_UPGRADE_LISTVERSION = "ListVersion";
static const QString DBUS_ATOMIC_UPGRADE_QUERYSUBJECT = "QuerySubject";
static const QString DBUS_ATOMIC_UPGRADE_ROLLBACK = "Rollback";

OSTreeWorkerThread::OSTreeWorkerThread(OperateType opType)
    : m_opType(opType)
    , m_operateID("")
{
    if (m_atomicUpgradeInterface == nullptr) {
        m_atomicUpgradeInterface = new QDBusInterface(DBUS_ATOMIC_UPGRADE_SERVICE,
                                                      DBUS_ATOMIC_UPGRADE_PATH,
                                                      DBUS_ATOMIC_UPGRADE_INTERFACE,
                                                      QDBusConnection::systemBus(),
                                                      this);
//        connect(m_atomicUpgradeInterface, SIGNAL(StateChanged(int,int,const QString &, const QString &)),
//                this,  SLOT(onStateChanged(int,int,const QString &, const QString &)));
    }
}

OSTreeWorkerThread::~OSTreeWorkerThread()
{
    if (m_atomicUpgradeInterface != nullptr) {
        delete m_atomicUpgradeInterface;
        m_atomicUpgradeInterface = nullptr;
    }
}

void OSTreeWorkerThread::run()
{
    switch (m_opType) {
        case OperateType::FactoryRestore : {
            this->factoryRestore(m_request);
            break;
        }
        default:
            break;
    }
}

void OSTreeWorkerThread::factoryRestore(const SystemRestoreRequest &request)
{
    m_operateID = request.operateID;
    QVariant runningProperty = m_atomicUpgradeInterface->property(DBUS_ATOMIC_UPGRADE_RUNNING);
    bool isRun = runningProperty.toBool();
    if (isRun) {
        qInfo()<<"factoryRestore OSTreeRunning";
        Response rsp(ErrorCode::OSTreeRunning, 100, 0, -2, OperateType::FactoryRestore, "", "", m_operateID, "");
        QString rspStr = Utils::JsonToQString(rsp.marshal());
        Q_EMIT error(rspStr);
        m_opType = OperateType::Invalid;
        m_operateID = "";
        return;
    }

    QString errMsg;
    QDBusReply<QStringList> listVersionReply = m_atomicUpgradeInterface->call(DBUS_ATOMIC_UPGRADE_LISTVERSION);
    if (!listVersionReply.isValid()) {
        errMsg = listVersionReply.error().message();
        qCritical() << Q_FUNC_INFO << "error: listVersionReply invalid, errMsg = "<<errMsg;
        Response rsp(ErrorCode::DbusError, 100, 0, -2, OperateType::FactoryRestore, errMsg, "", m_operateID, "");
        QString rspStr = Utils::JsonToQString(rsp.marshal());
        Q_EMIT error(rspStr);
        m_opType = OperateType::Invalid;
        m_operateID = "";
        return;
    }

    bool foundInitBackup = false;
    QStringList verList = listVersionReply.value();
    for (auto version : verList) {
        QStringList curVerList(version);
        QDBusReply<QStringList> subjectReply = m_atomicUpgradeInterface->call(DBUS_ATOMIC_UPGRADE_QUERYSUBJECT, curVerList);
        if (!subjectReply.isValid()) {
            errMsg = subjectReply.error().message();
            qCritical() << Q_FUNC_INFO << "subjectReply invalid, version = "<<version<<", errMsg = "<<errMsg;
            continue;
        }

        QJsonObject subjectObj = Utils::QStringToJson(subjectReply.value().first());
        if (!subjectObj.contains("SubmissionType")) {
            continue;
        }
        CommitType submissionType = static_cast<CommitType>(subjectObj.value("SubmissionType").toInt(-1));
        if (CommitType::InstallerCommit != submissionType) {
            continue;
        }

        foundInitBackup = true;
        QDBusMessage rollbackReply = m_atomicUpgradeInterface->call(DBUS_ATOMIC_UPGRADE_ROLLBACK, version);
        if (rollbackReply.type() != QDBusMessage::ReplyMessage) {
            QString errMsg = rollbackReply.errorMessage();
            qCritical() << Q_FUNC_INFO << "error: Rollback failed, version = " << version << ", errMsg = " << errMsg;
            Response rsp(ErrorCode::DbusError, 100, 0, -3, OperateType::FactoryRestore, errMsg, "", m_operateID, "");
            QString rspStr = Utils::JsonToQString(rsp.marshal());
            Q_EMIT error(rspStr);
            m_opType = OperateType::Invalid;
            m_operateID = "";
            return;
        }
    }

    qInfo()<<"factoryRestore, foundInitBackup = "<<foundInitBackup<<", opID: "<<m_operateID;
    if (foundInitBackup) {
        Response rsp(ErrorCode::OK, 100, 0, 0, OperateType::FactoryRestore, "", "", m_operateID, "");
        QString rspStr = Utils::JsonToQString(rsp.marshal());
        Q_EMIT success(rspStr);
    } else {
        Response rsp(ErrorCode::NoInitBackup, 100, 0, -4, OperateType::FactoryRestore, errMsg, "", m_operateID, "");
        QString rspStr = Utils::JsonToQString(rsp.marshal());
        Q_EMIT error(rspStr);
    }

    m_opType = OperateType::Invalid;
    m_operateID = "";
}

void OSTreeWorkerThread::setRequest(const SystemRestoreRequest &request)
{
    m_request = request;
}

void OSTreeWorkerThread::onStateChanged(int operate, int state, const QString &version, const QString &msg)
{
    qInfo()<<Q_FUNC_INFO<<", operate = "<<operate<<", state = "<<state<<", msg = "<<msg<<", version = "<<version;
}
