/*
 * Copyright 2023 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

#include <QCoreApplication>
#include <QSignalSpy>
#include <QtTest>

// 为了能够访问私有方法
#define private public
#define protected public
#include "../daemon/src/memorywatcher.h"
#undef private
#undef protected

class TestMemoryWatcher : public QObject
{
    Q_OBJECT

public:
    TestMemoryWatcher();
    ~TestMemoryWatcher();

private Q_SLOTS:
    void initTestCase();
    void cleanupTestCase();
    void init();
    void cleanup();

    // 测试构造函数和初始化
    void testConstructor();

    // 测试内存阈值初始化
    void testInitMemoryThreshold();

    // 测试内存检查方法
    void testCheckMemoryRemaining();

    // 测试开始和停止监视
    void testStartAndStop();

    // 测试信号发送
    void testResourceWarningSignal();

private:
    MemoryWatcher *m_watcher;
    std::map<resource::Resource, resource::ResourceUrgencyThreshold> createTestResourceThresholds();
};

TestMemoryWatcher::TestMemoryWatcher()
{
}

TestMemoryWatcher::~TestMemoryWatcher()
{
}

void TestMemoryWatcher::initTestCase()
{
}

void TestMemoryWatcher::cleanupTestCase()
{
}

void TestMemoryWatcher::init()
{
    m_watcher = new MemoryWatcher(createTestResourceThresholds());
}

void TestMemoryWatcher::cleanup()
{
    delete m_watcher;
    m_watcher = nullptr;
}

void TestMemoryWatcher::testConstructor()
{
    // 验证构造函数是否正确初始化了内部状态
    QVERIFY(m_watcher != nullptr);

    // 验证定时器是否被创建
    QVERIFY(m_watcher->m_timer != nullptr);

    // 验证内存阈值是否被正确初始化
    QCOMPARE(m_watcher->m_memoryThreshold[resource::ResourceUrgency::Low], 1000);
    QCOMPARE(m_watcher->m_memoryThreshold[resource::ResourceUrgency::Medium], 500);
    QCOMPARE(m_watcher->m_memoryThreshold[resource::ResourceUrgency::High], 200);
}

void TestMemoryWatcher::testInitMemoryThreshold()
{
    // 创建一个新的内存阈值
    auto thresholds = createTestResourceThresholds();
    thresholds[resource::Resource::Memory][resource::ResourceUrgency::Low] = 2000;
    thresholds[resource::Resource::Memory][resource::ResourceUrgency::Medium] = 1000;
    thresholds[resource::Resource::Memory][resource::ResourceUrgency::High] = 500;

    // 手动调用初始化阈值方法
    m_watcher->initMemoryThreshold(thresholds);

    // 验证阈值是否被正确更新
    QCOMPARE(m_watcher->m_memoryThreshold[resource::ResourceUrgency::Low], 2000);
    QCOMPARE(m_watcher->m_memoryThreshold[resource::ResourceUrgency::Medium], 1000);
    QCOMPARE(m_watcher->m_memoryThreshold[resource::ResourceUrgency::High], 500);
}

void TestMemoryWatcher::testCheckMemoryRemaining()
{
    // 设置一个非常高的阈值，确保会触发警告
    m_watcher->m_memoryThreshold[resource::ResourceUrgency::Low] = 1000000; // 1TB
    m_watcher->m_memoryThreshold[resource::ResourceUrgency::Medium] = 500000;
    m_watcher->m_memoryThreshold[resource::ResourceUrgency::High] = 100000;

    // 设置信号监视
    QSignalSpy spy(m_watcher, &MemoryWatcher::ResourceThresholdWarning);

    // 调用检查方法
    m_watcher->checkMemoryRemaining();

    // 应该会发出警告信号
    QVERIFY(spy.count() > 0);

    // 验证信号参数
    QList<QVariant> arguments = spy.takeFirst();
    QCOMPARE(arguments.at(0).toString(), QString("Memory"));
    QVERIFY(arguments.at(1).toInt() >= 1); // 应该是某种警告级别
}

void TestMemoryWatcher::testStartAndStop()
{
    // 验证定时器最初是停止的
    QVERIFY(!m_watcher->m_timer->isActive());

    // 启动监视
    m_watcher->start();

    // 验证定时器被激活
    QVERIFY(m_watcher->m_timer->isActive());

    // 停止监视
    m_watcher->stop();

    // 验证定时器被停止
    QVERIFY(!m_watcher->m_timer->isActive());
}

void TestMemoryWatcher::testResourceWarningSignal()
{
    // 设置阈值确保会触发警告
    m_watcher->m_memoryThreshold[resource::ResourceUrgency::Low] = 1000000; // 1TB

    // 设置信号监视
    QSignalSpy spy(m_watcher, &MemoryWatcher::ResourceThresholdWarning);

    // 启动监视并等待信号
    m_watcher->start();

    // 由于定时器设置为1秒，所以需要等待一段时间
    QTRY_VERIFY_WITH_TIMEOUT(spy.count() > 0, 2000); // 等待最多2秒

    // 验证信号参数
    QList<QVariant> arguments = spy.takeFirst();
    QCOMPARE(arguments.at(0).toString(), QString("Memory"));
    int warningLevel = arguments.at(1).toInt();
    QVERIFY(warningLevel >= 1 && warningLevel <= 3);

    // 清理
    m_watcher->stop();
}

std::map<resource::Resource, resource::ResourceUrgencyThreshold> TestMemoryWatcher::createTestResourceThresholds()
{
    std::map<resource::Resource, resource::ResourceUrgencyThreshold> thresholds;

    // 设置CPU资源的阈值（虽然不会被使用）
    resource::ResourceUrgencyThreshold cpuThresholds;
    cpuThresholds[resource::ResourceUrgency::Low] = 20;
    cpuThresholds[resource::ResourceUrgency::Medium] = 50;
    cpuThresholds[resource::ResourceUrgency::High] = 80;
    thresholds[resource::Resource::CPU] = cpuThresholds;

    // 设置内存资源的阈值，单位是MB
    resource::ResourceUrgencyThreshold memoryThresholds;
    memoryThresholds[resource::ResourceUrgency::Low] = 1000; // 1GB
    memoryThresholds[resource::ResourceUrgency::Medium] = 500; // 500MB
    memoryThresholds[resource::ResourceUrgency::High] = 200; // 200MB
    thresholds[resource::Resource::Memory] = memoryThresholds;

    return thresholds;
}

QTEST_MAIN(TestMemoryWatcher)
#include "tst_memorywatcher.moc"