//
// Created by zxm on 2022/12/13.
//
#include "RollbackNotify.h"
#include <QtDBus/QtDBus>
#include <QtDBus/QDBusInterface>
#include <QDebug>

namespace Notify {
 //   const QString DBUS_NOTIFY_SERVICE = "org.deepin.dde.Notification1";
 //   const QString DBUS_NOTIFY_PATH = "/org/deepin/dde/Notification1";
    const QString DBUS_NOTIFY_SERVICE = "org.freedesktop.Notifications";
    const QString DBUS_NOTIFY_PATH = "/org/freedesktop/Notifications";
    const QString DBUS_NOTIFY_INTERFACE = DBUS_NOTIFY_SERVICE;
    const QString DBUS_METHOD_NOTIFY = "Notify";

    const QString DBUS_UOS_RECOVERY_SERVICE = "com.deepin.uosrecovery";
    const QString DBUS_UOS_RECOVERY_SERVICE_PATH = "/com/deepin/uosrecovery";
    const QString DBUS_UOS_RECOVERY_INTERFACE = "com.deepin.daemon.uosrecovery";
    const QString DBUS_METHOD_CLEAR_AUTO_NOTIFY = "ClearRollbackAutoNotify";

    const QString BACKUP_PATH = "/backup/system/snapshots/";
    const QString UOS_RECOVERY_INI = "etc/uos-recovery/uos-recovery.ini";
    const QString RESTORE_GROUP = "restore";
    const QString RESTORE_BACKUP_POINT = "backup_point";
    const QString RESTORE_ROLLBACK_STATUS = "rollback_status";
    const QString RESTORE_ROLLBACK_VERSION = "rollback_version";
    const QString RESTORE_ROLLBACK_BEFORE_VERSION = "rollback_before_version";

    const int ROLLBACK_UNKNOWN = -1;
    const int ROLLBACK_SUCCESS = 0;
    const int ROLLBACK_FAILED = 1;
}

RollbackNotify::RollbackNotify()
{
}

RollbackNotify::~RollbackNotify()
{
}

bool RollbackNotify::clearRollbackAutoNotify()
{
    QString errMsg;
    QDBusInterface clearNotify(Notify::DBUS_UOS_RECOVERY_SERVICE,
                               Notify::DBUS_UOS_RECOVERY_SERVICE_PATH,
                               Notify::DBUS_UOS_RECOVERY_INTERFACE,
                               QDBusConnection::systemBus(),
                               this);

    if (!clearNotify.isValid()) {
        QDBusError dbusErr = clearNotify.lastError();
        if (QDBusError::ErrorType::NoError != dbusErr.type()) {
            errMsg = dbusErr.message();
            qCritical()<<"clearRollbackAutoNotify clearNotify invalid, errMsg = " << errMsg;
            return false;
        }
    }

    QDBusReply<void> clearNotifyRsp = clearNotify.call(Notify::DBUS_METHOD_CLEAR_AUTO_NOTIFY);
    if (!clearNotifyRsp.isValid()) {
        errMsg = clearNotifyRsp.error().message();
        qCritical()<<"clearRollbackAutoNotify error: clearNotifyRsp invalid, errMsg = "<<errMsg;
        return false;
    }
    return true;
}

bool RollbackNotify::notify()
{
    QString rootMountPoint = "/";
    QString recoveryConf = rootMountPoint + Notify::UOS_RECOVERY_INI;

    RollbackInfo rollbackInfo = RollbackNotify::getRollbackInfo(recoveryConf);
    RollbackNotify::sendNotify(rollbackInfo);
    if (Notify::ROLLBACK_UNKNOWN != rollbackInfo.status) {
        this->clearRollbackAutoNotify();
    }

    return true;
}

RollbackInfo RollbackNotify::getRollbackInfo(const QString &recoveryConf)
{
    RollbackInfo rollbackInfo;

    QSettings settings(recoveryConf, QSettings::IniFormat);
    settings.beginGroup(Notify::RESTORE_GROUP);
    QString backupPoint = settings.value(Notify::RESTORE_BACKUP_POINT).toString();
    int rollbackStatus = settings.value(Notify::RESTORE_ROLLBACK_STATUS, Notify::ROLLBACK_UNKNOWN).toInt();
    QString rollbackVersionDisplay = settings.value(Notify::RESTORE_ROLLBACK_VERSION).toString();
    QString rollbackBeforeVersionDisplay = settings.value(Notify::RESTORE_ROLLBACK_BEFORE_VERSION).toString();
    settings.endGroup();

    rollbackInfo.rollbackVersionDisplay = rollbackVersionDisplay;
    rollbackInfo.curVersionDisplay = rollbackBeforeVersionDisplay;
    rollbackInfo.status = rollbackStatus;

    return rollbackInfo;
}

bool RollbackNotify::sendNotify(const RollbackInfo &rollbackInfo)
{
    QString rollbackVersionDisplay = rollbackInfo.rollbackVersionDisplay;
    if (rollbackVersionDisplay.isEmpty() || Notify::ROLLBACK_UNKNOWN == rollbackInfo.status) {
        qInfo()<<"sendNotify rollbackVersion = "<<rollbackVersionDisplay<<", status = "<<rollbackInfo.status;
        return true;
    }
    
    QString appName = QObject::tr("Backup and Restore");
    quint32 replacesId = 101;
    QString appIcon = "uos-recovery";
    QString summary = QObject::tr("System Recovery");
    QString body;
    if (Notify::ROLLBACK_SUCCESS == rollbackInfo.status) {
        body = tr("Your system is successfully rolled back to %1.").arg(rollbackInfo.rollbackVersionDisplay);
     //   body = tr("Successfully rolled back to %1.").arg(rollbackInfo.rollbackVersionDisplay);
    } else if (Notify::ROLLBACK_FAILED == rollbackInfo.status) {
        body = tr("Rollback failed. The system is reverted to %1.").arg(rollbackInfo.curVersionDisplay);
    }
    QStringList actions = {};
    QVariantMap hints;
    // The timeout time in milliseconds since the display of the notification at which the notification should automatically close.
    qint32 expireTimeout = 8000;

    QString errMsg;

    QDBusInterface notify(Notify::DBUS_NOTIFY_SERVICE,
                          Notify::DBUS_NOTIFY_PATH,
                          Notify::DBUS_NOTIFY_INTERFACE,
                          QDBusConnection::sessionBus());

    if (!notify.isValid()) {
        QDBusError dbusErr = notify.lastError();
        if (QDBusError::ErrorType::NoError != dbusErr.type()) {
            errMsg = dbusErr.message();
            qCritical()<<"sendNotify notify invalid, errMsg = " << errMsg<<", rollbackVersion = "<<rollbackVersionDisplay;
            return false;
        }
    }

    QDBusReply<quint32> notifyRsp = notify.call(Notify::DBUS_METHOD_NOTIFY, appName, replacesId, appIcon,
                                                summary, body, actions, hints, expireTimeout);
    if (!notifyRsp.isValid()) {
        errMsg = notifyRsp.error().message();
        qCritical()<<"sendNotify error: notifyRsp invalid, errMsg = "<<errMsg<<", rollbackVersion = "<<rollbackVersionDisplay;
        return false;
    }

    return true;
}
