// SPDX-FileCopyrightText: 2025 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

#ifndef ERR_NOTIFIER_SERVICE_H
#define ERR_NOTIFIER_SERVICE_H

#include <DConfig>

#include <QDBusAbstractAdaptor>
#include <QDBusConnection>
#include <QDBusMessage>
#include <QDBusObjectPath>
#include <QLoggingCategory>
#include <QObject>
#include <QString>
#include <QVariantMap>

using DTK_CORE_NAMESPACE::DConfig;

Q_DECLARE_LOGGING_CATEGORY(lc_err_notifier)

enum class AppIdentifierType {
    AM,             // ApplicationManager D-Bus path
    SYSTEM_SERVICE, // System service
    USER_SERVICE    // User service
};

enum class ExportLogError { None = 0, InProgress, AuthenticationFailed, SystemServiceUnavailable };

class ErrNotifierService : public QObject
{
    Q_OBJECT

public:
    explicit ErrNotifierService(const QDBusConnection &connection, QObject *parent = nullptr);
    ~ErrNotifierService() override;

    bool initialize();

    bool notificationEnabled() const;
    void setNotificationEnabled(bool enabled);

    ExportLogError doExportLog();

private slots:
    void handleErrorOccurred(const QVariantMap &payload);
    void handlePortalResponse(uint response, const QVariantMap &results);
    void handleConfigValueChanged(const QString &key);

private:
    void emitPropertiesChanged(const QString &propertyName, const QVariant &value);
    void initErrorSignalSubscription();
    void loadShowReadOnlyProtectionConfig();
    void showNotification(const QString &summary,
                          const QString &body,
                          int timeout_ms = 5000,
                          bool add_action = false);
    ExportLogError requestLogFromSystemService();
    void cleanupCachedLogFd();
    void openExportDialog();
    bool startPortalSaveDialog();
    void cleanupPortalRequest();
    void handleExportPath(const QString &path);
    bool exportLogToPath(const QString &path);
    QString applicationLabelFromPayload(const QVariantMap &payload) const;
    QString identifyApplication(quint32 pid, const QString &cgroup) const;
    QString parseAppIdentifierFromCgroup(const QString &cgroup, AppIdentifierType &outType) const;
    QString identifyFromCgroupPath(const QString &cgroup) const;
    QString getLocalizedName(const QString &appInstancePath, bool truncateLeft = true) const;
    QString extractLocalizedValue(const QMap<QString, QString> &localeMap) const;
    QString variantToString(const QVariant &value) const;
    quint32 variantToUint(const QVariant &value) const;
    QString defaultDirectory() const;
    QString defaultFileName() const;
    QString getPackageNameFromService(const QString &serviceName,
                                      AppIdentifierType serviceType) const;
    QString extractServiceFilePath(const QString &systemctlOutput) const;
    QString queryPackageByPath(const QString &filePath) const;

    QDBusConnection m_connection;
    bool m_service_registered = false;
    bool m_object_registered = false;
    bool m_export_in_progress = false;
    uint m_last_notification_id = 0;
    QDBusObjectPath m_portal_request_path;
    bool m_notification_enabled = false;
    bool m_show_readonly_protection = true;
    DConfig *m_config = nullptr;
    int m_cached_log_fd = -1;

    friend class ErrNotifierAdaptor;
};

// D-Bus Adaptor for ErrNotifierService
class ErrNotifierAdaptor : public QDBusAbstractAdaptor
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "org.deepin.immutable.ErrNotifier1")
    Q_PROPERTY(bool NotificationEnabled READ notificationEnabled WRITE setNotificationEnabled)

public:
    explicit ErrNotifierAdaptor(ErrNotifierService *service);

    bool notificationEnabled() const;
    void setNotificationEnabled(bool enabled);

public slots:
    void ExportLog(const QDBusMessage &message);

private:
    ErrNotifierService *m_service;
};

#endif // ERR_NOTIFIER_SERVICE_H
