#include <QtTest>
#include <QSignalSpy>
#include <QDBusConnection>
#define private public
#include "../../../src/main/account-information.h"
#undef private

using namespace UkuiShortcut;

class FakeBatteryService : public QObject
{
    Q_OBJECT
    Q_CLASSINFO("D-Bus Interface", "org.ukui.upower.battery")

public:
    explicit FakeBatteryService(QObject *parent = nullptr) : QObject(parent) {}

public slots:
    QString IconName() const { return "battery-good-symbolic"; }
    double Percentage() const { return 66.0; }
    bool ShowIcon() const { return true; }
    QString GetBatteryTooltip() const { return "Battery 66%"; }
    bool IsPresent() const { return true; }

signals:
    void BatteryIcon(const QString &iconName);
    void PercentageChanged(double percentage);
    void BatteryShowIcon(bool enable);
    void BatteryTooltip(const QString &tooltip);
    void IsPresentChanged(bool present);
};


class accountInformation_test : public QObject
{
    Q_OBJECT

private slots:
    // AccountInformation 测试
    void test_createAccountInformation();
    void test_getUsername();
    void test_getRealName();
    void test_getIconFile_default();
    void test_getAccountType_default();
    void test_getAccountType_unknown();
    void test_getUserObjectPath_doesNotCrash();
    void test_getUserInformation_invalidPath_defaults();
    void test_currentAccountUpdateSlot_iconFile();
    void test_currentAccountUpdateSlot_userName();
    void test_currentAccountUpdateSlot_realName();
    void test_currentAccountUpdateSlot_accountType();
    void test_currentAccountUpdateSlot_multipleFields();
    void test_currentAccountUpdateSlot_emptyMap();
    void test_currentAccountUpdateSlot_emitsSignal();

    // PowerButton 测试
    void test_createPowerButton();
    void test_powerButton_defaultIsEnable();
    void test_powerButton_defaultIcon();
    void test_powerButton_defaultTooltip();
    void test_powerButton_defaultPercentage();
    void test_powerButton_defaultIsPresent();
    void test_powerButton_onBatteryIconChanged();
    void test_powerButton_onBatteryIconChanged_sameIcon();
    void test_powerButton_onPercentageChanged();
    void test_powerButton_onPercentageChanged_sameValue();
    void test_powerButton_onBatteryShowIcon();
    void test_powerButton_onBatteryShowIcon_sameValue();
    void test_powerButton_onBatteryTooltip();
    void test_powerButton_onBatteryTooltip_sameValue();
    void test_powerButton_onIsPresentChanged();
    void test_powerButton_onIsPresentChanged_sameValue();
    void test_powerButton_onConnectorReady_invalidInterface();
    void test_powerButton_onConnectorReady_validInterface();
    void test_powerButton_onServiceUnregistered();
    void test_openMethods_doesNotCrash();
};

// 辅助函数：调用 AccountInformation 的私有槽 currentAccountUpdateSlot
static void invokeCurrentAccountUpdateSlot(AccountInformation *info,
                                           const QString &property,
                                           const QMap<QString, QVariant> &propertyMap,
                                           const QStringList &propertyList)
{
    QMetaObject::invokeMethod(info, "currentAccountUpdateSlot",
                              Q_ARG(QString, property),
                              Q_ARG(QVariantMap, propertyMap),
                              Q_ARG(QStringList, propertyList));
}

// 辅助函数：调用 PowerButton 的私有槽
static void invokeOnBatteryIconChanged(PowerButton *button, const QString &iconName)
{
    QMetaObject::invokeMethod(button, "onBatteryIconChanged", Q_ARG(QString, iconName));
}

static void invokeOnPercentageChanged(PowerButton *button, double percentage)
{
    QMetaObject::invokeMethod(button, "onPercentageChanged", Q_ARG(double, percentage));
}

static void invokeOnBatteryShowIcon(PowerButton *button, bool isEnable)
{
    QMetaObject::invokeMethod(button, "onBatteryShowIcon", Q_ARG(bool, isEnable));
}

static void invokeOnBatteryTooltip(PowerButton *button, const QString &tooltip)
{
    QMetaObject::invokeMethod(button, "onBatteryTooltip", Q_ARG(QString, tooltip));
}

static void invokeOnIsPresentChanged(PowerButton *button, bool isPresent)
{
    QMetaObject::invokeMethod(button, "onIsPresentChanged", Q_ARG(bool, isPresent));
}

static void invokeOnConnectorReady(PowerButton *button, QDBusInterface *iface)
{
    QMetaObject::invokeMethod(button, "onConnectorReady", Q_ARG(QDBusInterface *, iface));
}

static void invokeOnServiceUnregistered(PowerButton *button)
{
    QMetaObject::invokeMethod(button, "onServiceUnregistered");
}

void accountInformation_test::test_createAccountInformation()
{
    AccountInformation info;
    QVERIFY(true);
}

void accountInformation_test::test_getUsername()
{
    AccountInformation info;
    QString username = info.getUsername();
    QVERIFY(username.isNull() || !username.isNull());
}

void accountInformation_test::test_getRealName()
{
    AccountInformation info;
    QString realName = info.getRealName();
    QVERIFY(realName.isNull() || !realName.isNull());
}

void accountInformation_test::test_getIconFile_default()
{
    AccountInformation info;
    QString iconFile = info.getIconFile();
    // 如果无法获取用户信息，应返回默认图标
    QVERIFY(!iconFile.isEmpty());
}

void accountInformation_test::test_getAccountType_default()
{
    AccountInformation info;
    QString accountType = info.getAccountType();
    QVERIFY(accountType.isEmpty() || !accountType.isEmpty());
}

void accountInformation_test::test_getAccountType_unknown()
{
    AccountInformation info;
    QMap<QString, QVariant> propertyMap;
    propertyMap.insert("AccountType", 2);

    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());
    QCOMPARE(info.getAccountType(), QString(""));
}

void accountInformation_test::test_getUserObjectPath_doesNotCrash()
{
    AccountInformation info;
    const QStringList users = info.getUserObjectPath();
    QVERIFY(users.size() >= 0);
}

void accountInformation_test::test_getUserInformation_invalidPath_defaults()
{
    AccountInformation info;
    const UserInformation user = info.GetUserInformation("/org/freedesktop/Accounts/User999999");

    QCOMPARE(user.current, false);
    QCOMPARE(user.isLogged, false);
    QCOMPARE(user.autologin, false);
}

void accountInformation_test::test_currentAccountUpdateSlot_iconFile()
{
    AccountInformation info;
    QSignalSpy spy(&info, &AccountInformation::userInfoChanged);

    QMap<QString, QVariant> propertyMap;
    propertyMap.insert("IconFile", "/test/icon.png");

    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());

    QCOMPARE(spy.count(), 1);
    QCOMPARE(info.getIconFile(), QString("/test/icon.png"));
}

void accountInformation_test::test_currentAccountUpdateSlot_userName()
{
    AccountInformation info;
    QSignalSpy spy(&info, &AccountInformation::userInfoChanged);

    QMap<QString, QVariant> propertyMap;
    propertyMap.insert("UserName", "testuser");

    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());

    QCOMPARE(spy.count(), 1);
    QCOMPARE(info.getUsername(), QString("testuser"));
}

void accountInformation_test::test_currentAccountUpdateSlot_realName()
{
    AccountInformation info;
    QSignalSpy spy(&info, &AccountInformation::userInfoChanged);

    QMap<QString, QVariant> propertyMap;
    propertyMap.insert("RealName", "Test User");

    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());

    QCOMPARE(spy.count(), 1);
    QCOMPARE(info.getRealName(), QString("Test User"));
}

void accountInformation_test::test_currentAccountUpdateSlot_accountType()
{
    AccountInformation info;
    QSignalSpy spy(&info, &AccountInformation::userInfoChanged);

    QMap<QString, QVariant> propertyMap;
    propertyMap.insert("AccountType", 1);

    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());

    QCOMPARE(spy.count(), 1);
    QCOMPARE(info.getAccountType(), QObject::tr("Administrator"));
}

void accountInformation_test::test_currentAccountUpdateSlot_multipleFields()
{
    AccountInformation info;
    QSignalSpy spy(&info, &AccountInformation::userInfoChanged);

    QMap<QString, QVariant> propertyMap;
    propertyMap.insert("UserName", "multiuser");
    propertyMap.insert("RealName", "Multi User");
    propertyMap.insert("IconFile", "/multi/icon.png");
    propertyMap.insert("AccountType", 0);

    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());

    QCOMPARE(spy.count(), 1);
    QCOMPARE(info.getUsername(), QString("multiuser"));
    QCOMPARE(info.getRealName(), QString("Multi User"));
    QCOMPARE(info.getIconFile(), QString("/multi/icon.png"));
    QCOMPARE(info.getAccountType(), QObject::tr("Standard user"));
}

void accountInformation_test::test_currentAccountUpdateSlot_emptyMap()
{
    AccountInformation info;
    QSignalSpy spy(&info, &AccountInformation::userInfoChanged);

    QMap<QString, QVariant> propertyMap;
    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());

    QCOMPARE(spy.count(), 1);
}

void accountInformation_test::test_currentAccountUpdateSlot_emitsSignal()
{
    AccountInformation info;
    QSignalSpy spy(&info, &AccountInformation::userInfoChanged);

    QMap<QString, QVariant> propertyMap;
    propertyMap.insert("IconFile", "/icon1.png");
    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());

    propertyMap.clear();
    propertyMap.insert("IconFile", "/icon2.png");
    invokeCurrentAccountUpdateSlot(&info, "", propertyMap, QStringList());

    QCOMPARE(spy.count(), 2);
}

void accountInformation_test::test_createPowerButton()
{
    PowerButton button;
    QVERIFY(true);
}

void accountInformation_test::test_powerButton_defaultIsEnable()
{
    PowerButton button;
    QCOMPARE(button.isEnable(), false);
}

void accountInformation_test::test_powerButton_defaultIcon()
{
    PowerButton button;
    QCOMPARE(button.icon(), QString(""));
}

void accountInformation_test::test_powerButton_defaultTooltip()
{
    PowerButton button;
    QCOMPARE(button.tooltip(), QString(""));
}

void accountInformation_test::test_powerButton_defaultPercentage()
{
    PowerButton button;
    QCOMPARE(button.percentage(), QString(""));
}

void accountInformation_test::test_powerButton_defaultIsPresent()
{
    PowerButton button;
    QCOMPARE(button.isPresent(), false);
}

void accountInformation_test::test_powerButton_onBatteryIconChanged()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::iconChanged);
    invokeOnBatteryIconChanged(&button, "battery-full");
    QCOMPARE(button.icon(), QString("battery-full"));
    QCOMPARE(spy.count(), 1);
}

void accountInformation_test::test_powerButton_onBatteryIconChanged_sameIcon()
{
    PowerButton button;
    invokeOnBatteryIconChanged(&button, "battery-low");
    QSignalSpy spy(&button, &PowerButton::iconChanged);
    invokeOnBatteryIconChanged(&button, "battery-low");
    QCOMPARE(spy.count(), 0);
}

void accountInformation_test::test_powerButton_onPercentageChanged()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::percentageChanged);
    invokeOnPercentageChanged(&button, 85.6);
    QCOMPARE(button.percentage(), QString("86"));
    QCOMPARE(spy.count(), 1);
}

void accountInformation_test::test_powerButton_onPercentageChanged_sameValue()
{
    PowerButton button;
    invokeOnPercentageChanged(&button, 50.0);
    QSignalSpy spy(&button, &PowerButton::percentageChanged);
    invokeOnPercentageChanged(&button, 50.4);
    QCOMPARE(spy.count(), 0);
}

void accountInformation_test::test_powerButton_onBatteryShowIcon()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::isEnableChanged);
    invokeOnBatteryShowIcon(&button, true);
    QCOMPARE(button.isEnable(), true);
    QCOMPARE(spy.count(), 1);
}

void accountInformation_test::test_powerButton_onBatteryShowIcon_sameValue()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::isEnableChanged);
    invokeOnBatteryShowIcon(&button, false);
    QCOMPARE(spy.count(), 0);
}

void accountInformation_test::test_powerButton_onBatteryTooltip()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::tooltipChanged);
    invokeOnBatteryTooltip(&button, "Battery 85%");
    QCOMPARE(button.tooltip(), QString("Battery 85%"));
    QCOMPARE(spy.count(), 1);
}

void accountInformation_test::test_powerButton_onBatteryTooltip_sameValue()
{
    PowerButton button;
    invokeOnBatteryTooltip(&button, "Battery 50%");
    QSignalSpy spy(&button, &PowerButton::tooltipChanged);
    invokeOnBatteryTooltip(&button, "Battery 50%");
    QCOMPARE(spy.count(), 0);
}

void accountInformation_test::test_powerButton_onIsPresentChanged()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::isPresentChanged);
    invokeOnIsPresentChanged(&button, true);
    QCOMPARE(button.isPresent(), true);
    QCOMPARE(spy.count(), 1);
}

void accountInformation_test::test_powerButton_onIsPresentChanged_sameValue()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::isPresentChanged);
    invokeOnIsPresentChanged(&button, false);
    QCOMPARE(spy.count(), 0);
}

void accountInformation_test::test_powerButton_onConnectorReady_invalidInterface()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::isEnableChanged);
    QDBusInterface invalidIface("invalid.service",
                                "/invalid/path",
                                "invalid.interface",
                                QDBusConnection::sessionBus());
    invokeOnConnectorReady(&button, &invalidIface);
    QCOMPARE(spy.count(), 0);
}

void accountInformation_test::test_powerButton_onConnectorReady_validInterface()
{
    if (!QDBusConnection::sessionBus().isConnected()) {
        QSKIP("Session bus is not available.");
    }

    FakeBatteryService service;
    QVERIFY(QDBusConnection::sessionBus().registerService("org.ukui.upower"));
    QVERIFY(QDBusConnection::sessionBus().registerObject("/upower/BatteryInfo",
                                                         &service,
                                                         QDBusConnection::ExportAllSlots | QDBusConnection::ExportAllSignals));

    PowerButton button;
    QSignalSpy enableSpy(&button, &PowerButton::isEnableChanged);
    QDBusInterface *iface = new QDBusInterface("org.ukui.upower",
                                               "/upower/BatteryInfo",
                                               "org.ukui.upower.battery",
                                               QDBusConnection::sessionBus(),
                                               &button);
    QVERIFY(iface->isValid());

    invokeOnConnectorReady(&button, iface);

    QTRY_VERIFY(enableSpy.count() >= 1);
    QTRY_COMPARE(button.icon(), QString("battery-good-symbolic"));
    QTRY_COMPARE(button.percentage(), QString("66"));
    QTRY_COMPARE(button.tooltip(), QString("Battery 66%"));
    QTRY_COMPARE(button.isPresent(), true);
    QCOMPARE(button.isEnable(), true);

    QDBusConnection::sessionBus().unregisterObject("/upower/BatteryInfo");
    QDBusConnection::sessionBus().unregisterService("org.ukui.upower");
}

void accountInformation_test::test_powerButton_onServiceUnregistered()
{
    PowerButton button;
    QSignalSpy spy(&button, &PowerButton::isEnableChanged);
    invokeOnServiceUnregistered(&button);
    QCOMPARE(button.isEnable(), false);
    QCOMPARE(spy.count(), 1);
}

void accountInformation_test::test_openMethods_doesNotCrash()
{
    AccountInformation info;
    info.openUserCenter();
    info.openPeonyUser();
    info.openControlCenter();
    info.openPowerButton();
    QTest::qWait(50);
    QVERIFY(true);
}

QTEST_MAIN(accountInformation_test)

#include "account-information-test.moc"
