#include "aptssupdater.h"
#include <QProcess>
#include <QTextStream>
#include <QRegularExpression>
#include <QFile>
#include <QDir>
#include <qdebug.h>

aptssUpdater::aptssUpdater(QWidget *parent)
    : QWidget(parent)
{
    packageName = getUpdateablePackages();
    apmPackageName = getApmUpdateablePackages();
}

QStringList aptssUpdater::getUpdateablePackages()
{
    QStringList packageDetails;

    // 检查aptss命令是否存在
    QProcess checkProcess;
    checkProcess.start("which", QStringList() << "aptss");
    if (!checkProcess.waitForFinished(5000) || checkProcess.exitCode() != 0) {
        qDebug() << "aptss命令不存在，跳过Spark更新检查";
        return packageDetails;
    }

    QProcess process;
    QString command = R"(env LANGUAGE=en_US /usr/bin/apt -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf list --upgradable -o Dir::Etc::sourcelist="/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/aptss.list" -o Dir::Etc::sourceparts="/dev/null" -o APT::Get::List-Cleanup="0" | awk 'NR>1')";

    process.start("bash", QStringList() << "-c" << command);
    if (!process.waitForFinished(30000)) { // 30秒超时
        qWarning() << "Process failed to finish within 30 seconds.";
        process.kill();
        return packageDetails;
    }

    QString output = process.readAllStandardOutput();
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
        QStringList lines = output.split('\n', Qt::SkipEmptyParts);
#else
        QStringList lines = output.split('\n', QString::SkipEmptyParts);
#endif


    // 创建临时文件
    QTemporaryFile tempFile;
    tempFile.setAutoRemove(false);
    if (tempFile.open()) {
        QTextStream stream(&tempFile);
        
        for (const QString &line : lines) {
            QRegularExpression regex(R"(([\w\-\+\.]+)/\S+\s+([^\s]+)\s+\S+\s+\[upgradable from: ([^\]]+)\])");
            QRegularExpressionMatch match = regex.match(line);
            if (match.hasMatch()) {
                QString name = match.captured(1);
                QString newVersion = match.captured(2);
                QString oldVersion = match.captured(3);
                
                // 检查版本是否相同，相同则跳过
                if (newVersion == oldVersion) {
                    qDebug() << "跳过版本相同的包:" << name << "(" << oldVersion << "→" << newVersion << ")";
                    continue;
                }
                
                // 写入内存列表
                packageDetails << QString("%1: %2 → %3").arg(name, oldVersion, newVersion);
                
                // 写入临时文件（原始数据）
                stream << name << "|" << oldVersion << "|" << newVersion << "\n";
            }
        }
        tempFile.close();
        m_tempFilePath = tempFile.fileName();
        qDebug()<< "临时文件路径：" << m_tempFilePath;
        
    } else {
        qWarning() << "无法创建临时文件";
    }

    return packageDetails;
}


QStringList aptssUpdater::getPackageSizes()
{
    QStringList packageDetails;

    // 获取可更新包名列表
    QStringList updateablePackages;
    for (const QString &pkgInfo : packageName) {
        updateablePackages << pkgInfo.section(":", 0, 0).trimmed();
    }

    foreach (const QString &packageName, updateablePackages) {
        QProcess process;  // 在循环内部创建新的QProcess实例
        
        // 构建新命令（包含包名参数）
        QString command = QString("/usr/bin/apt download %1 --print-uris -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf "
                                  "-o Dir::Etc::sourcelist=\"/opt/durapps/spark-store/bin/apt-fast-conf/sources.list.d/aptss.list\" "
                                  "-o Dir::Etc::sourceparts=\"/dev/null\"").arg(packageName);

        process.start("bash", QStringList() << "-c" << command);
        if (!process.waitForFinished(30000)) { // 30秒超时
            qWarning() << "获取包信息失败：" << packageName << "（超时）";
            process.kill();
            continue;
        }

        QString output = process.readAllStandardOutput();
        // 使用正则匹配所有信息
        // 调整正则表达式匹配分组
        QRegularExpression regex(R"('([^']+)'\s+(\S+)\s+(\d+)\s+SHA512:([^\s]+))");  // 分组1:URL 分组2:文件名 分组3:大小 分组4:SHA512
        QRegularExpressionMatch match = regex.match(output);

        if (match.hasMatch()) {
            QString url = match.captured(1);
            QString fileName = match.captured(2);
            QString size = match.captured(3);
            QString sha512 = match.captured(4);
            
            // 调整字段顺序：包名 | 大小 | URL | SHA512
            packageDetails << QString("%1: %2|%3|%4").arg(packageName, size, url, sha512);
        }
    }

    qDebug() << "完整包信息：" << packageDetails;
    return packageDetails;
}





QStringList aptssUpdater::getDesktopAppNames()
{
    QStringList appNames;
    
    // 获取当前系统语言环境
    QString lang = QLocale().name().replace("_", "-");

    // 遍历所有可更新包（复用已有的临时文件数据）
    QStringList packages = packageName;
    
    foreach (const QString &package, packages) {
        QProcess dpkgProcess;  // 在循环内部创建新的QProcess实例
        
        QString packageName = package.split(":")[0];
        QString finalName = packageName; // 默认使用包名
        
        // 获取包文件列表
        dpkgProcess.start("dpkg", QStringList() << "-L" << packageName);
        if (!dpkgProcess.waitForFinished(30000)) { // 30秒超时
            qWarning() << "获取包文件列表失败：" << packageName << "（超时）";
            dpkgProcess.kill();
            continue;
        }
        
        // 修复：添加这行代码来获取进程输出
        QString output = dpkgProcess.readAllStandardOutput();
        
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
        QStringList files = output.split('\n', Qt::SkipEmptyParts);
#else
        QStringList files = output.split('\n', QString::SkipEmptyParts);
#endif

        // 先检查常规应用目录
        QStringList regularDesktopFiles = files.filter("/usr/share/applications/");
        QString regularAppName;
        if (!regularDesktopFiles.isEmpty()) {
            checkDesktopFiles(regularDesktopFiles, regularAppName, lang, packageName);
        }
        
        // 如果常规目录没有找到，再检查特殊目录
        if (regularAppName.isEmpty()) {
            QStringList specialDesktopFiles = files.filter(QRegularExpression(QString("/opt/apps/%1/entries/applications").arg(packageName)));
            QString specialAppName;
            if (!specialDesktopFiles.isEmpty()) {
                checkDesktopFiles(specialDesktopFiles, specialAppName, lang, packageName);
                if (!specialAppName.isEmpty()) {
                    finalName = specialAppName;
                }
            }
        } else {
            finalName = regularAppName;
        }
        
        // 输出格式为[软件名|包名]
        appNames << QString("[%1|%2]").arg(finalName, packageName);
    }
    qDebug()<< "应用名称列表：" << appNames;
    return appNames;
}




bool aptssUpdater::checkDesktopFiles(const QStringList &desktopFiles, QString &appName, const QString &lang, const QString &packageName)
{
    QString lastValidName; 
    QRegularExpression noDisplayRe("^NoDisplay=(true|True)");
    QRegularExpression nameRe("^Name\\[?" + lang + "?\\]?=(.*)");
    QRegularExpression nameOrigRe("^Name=(.*)");

    foreach (const QString &filePath, desktopFiles) {
        if (!filePath.endsWith(".desktop")) continue;

        QFile file(filePath);
        if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) continue;

        bool skip = false;
        QString currentName;
        
        QTextStream in(&file);
        while (!in.atEnd()) {
            QString line = in.readLine().trimmed();
            
            // 检查NoDisplay属性
            if (line.startsWith("NoDisplay=")) {
                if (noDisplayRe.match(line).hasMatch()) {
                    skip = true;
                    break;
                }
            }
            
            // 优先匹配本地化名称
            if (currentName.isEmpty()) {
                QRegularExpressionMatch match = nameRe.match(line);
                if (match.hasMatch()) {
                    currentName = match.captured(1);
                    continue;
                }
                
                // 匹配原始名称
                match = nameOrigRe.match(line);
                if (match.hasMatch()) {
                    currentName = match.captured(1);
                }
            }
        }
        
        if (!skip && !currentName.isEmpty()) {
            lastValidName = currentName;
        }
    }

    // 处理最终的有效名称
    if (!lastValidName.isEmpty()) {
        appName = lastValidName;  // 直接赋值而不是使用<<
        return true;
    }
    
    // 回退到包名
    appName = packageName;
    return false;
}

QStringList aptssUpdater::getPackageIcons()
{
    QStringList packageIcons;
    
    // 遍历所有可更新包
    QStringList packages = packageName;
    
    foreach (const QString &package, packages) {
        QProcess dpkgProcess;  // 在循环内部创建新的QProcess实例
        
        QString packageName = package.split(":")[0];
        QString iconPath = ":/resources/default_icon.png"; // 默认图标
        
        // 获取包文件列表
        dpkgProcess.start("dpkg", QStringList() << "-L" << packageName);
        if (!dpkgProcess.waitForFinished(30000)) { // 30秒超时
            qWarning() << "获取包文件列表失败：" << packageName << "（超时）";
            dpkgProcess.kill();
            packageIcons << QString("%1: %2").arg(packageName, iconPath);
            continue;
        }
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
        QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', Qt::SkipEmptyParts);
#else
        QStringList files = QString(dpkgProcess.readAllStandardOutput()).split('\n', QString::SkipEmptyParts);
#endif
        
        
        // 查找.desktop文件
        QStringList desktopFiles = files.filter(QRegularExpression("/(usr/share|opt/apps)/.*\\.desktop$"));
        
        // 从.desktop文件中提取图标
        foreach (const QString &desktopFile, desktopFiles) {
            QFile file(desktopFile);
            if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
                QTextStream in(&file);
                while (!in.atEnd()) {
                    QString line = in.readLine().trimmed();
                    if (line.startsWith("Icon=")) {
                        QString iconName = line.mid(5).trimmed();
                        
                        // 处理相对图标名（如Icon=vscode）
                        if (!iconName.contains('/')) {
                            // 查找标准图标路径
                            QStringList iconPaths = {
                                QString("/usr/share/pixmaps/%1.png").arg(iconName),
                                QString("/usr/share/icons/hicolor/48x48/apps/%1.png").arg(iconName),
                                QString("/usr/share/icons/hicolor/scalable/apps/%1.svg").arg(iconName),
                                QString("/opt/apps/%1/entries/icons/hicolor/48x48/apps/%2.png").arg(packageName, iconName)
                            };
                            
                            foreach (const QString &path, iconPaths) {
                                if (QFile::exists(path)) {
                                    iconPath = path;
                                    qDebug() << "找到图标文件:" << path;
                                    break;
                                }
                            }
                        } else {
                            // 已经是绝对路径
                            if (QFile::exists(iconName)) {
                                iconPath = iconName;
                                qDebug() << "使用绝对路径图标文件:" << iconName;
                            }
                        }
                        break;
                    }
                }
                file.close();
            }
        }
        
        // 如果.desktop中没有找到图标，尝试直接查找包中的图标文件
        if (iconPath == ":/resources/default_icon.png") {
            qDebug() << "未在.desktop文件中找到图标，尝试直接查找包中的图标文件";
            QStringList iconFiles = files.filter(QRegularExpression("/(usr/share/pixmaps|usr/share/icons|opt/apps/.*/entries/icons)/.*\\.(png|svg)$"));
            if (!iconFiles.isEmpty()) {
                iconPath = iconFiles.first();
                qDebug() << "从包中找到图标文件:" << iconPath;
            } else {
                qDebug() << "未在包中找到图标文件，使用默认图标";
            }
        }
        
        qDebug() << "包名:" << packageName << "图标路径:" << iconPath;
        packageIcons << QString("%1: %2").arg(packageName, iconPath);
    }
    
    return packageIcons;
}


QJsonArray aptssUpdater::getUpdateInfoAsJson()
{
    QJsonArray jsonArray;
    
    // 获取所有需要的信息
    QStringList sizes = getPackageSizes();
    QStringList names = getDesktopAppNames();
    QStringList icons = getPackageIcons();
    
    // 创建包名到各种信息的映射
    QHash<QString, QHash<QString, QString>> packageInfo;
    
    // 解析包版本信息
    for (const QString &pkg : packageName) {
        QStringList parts = pkg.split(": ");
        if (parts.size() >= 2) {
            QString packageName = parts[0];
            QStringList versions = parts[1].split(" → ");
            if (versions.size() == 2) {
                packageInfo[packageName]["current_version"] = versions[0];
                packageInfo[packageName]["new_version"] = versions[1];
            }
        }
    }
    
    // 解析包详细信息（新增部分）
    for (const QString &sizeInfo : sizes) {
        QStringList parts = sizeInfo.split(": ");
        if (parts.size() == 2) {
            QString packageName = parts[0];
            QStringList details = parts[1].split("|");
            if (details.size() == 3) {  // 现在包含大小|URL|SHA512
                packageInfo[packageName]["size"] = details[0];
                packageInfo[packageName]["url"] = details[1];
                packageInfo[packageName]["sha512"] = details[2];
            }
        }
    }
    
    // 解析应用名称信息
    for (const QString &nameInfo : names) {
        if (nameInfo.startsWith("[") && nameInfo.endsWith("]")) {
            QString content = nameInfo.mid(1, nameInfo.length() - 2);
            QStringList parts = content.split("|");
            if (parts.size() == 2) {
                QString displayName = parts[0];
                QString packageName = parts[1];
                packageInfo[packageName]["display_name"] = displayName;
            }
        }
    }
    
    // 解析图标信息
    for (const QString &iconInfo : icons) {
        QStringList parts = iconInfo.split(": ");
        if (parts.size() == 2) {
            QString packageName = parts[0];
            packageInfo[packageName]["icon"] = parts[1].trimmed();
        }
    }
    
    // 构建JSON数组
    for (const QString &packageName : packageInfo.keys()) {
        QJsonObject jsonObj;
        jsonObj["package"] = packageName;
        
        // 使用显示名称(如果有)，否则使用包名
        if (packageInfo[packageName].contains("display_name")) {
            jsonObj["name"] = packageInfo[packageName]["display_name"];
        } else {
            jsonObj["name"] = packageName;
        }
        
        jsonObj["current_version"] = packageInfo[packageName]["current_version"];
        jsonObj["new_version"] = packageInfo[packageName]["new_version"];
        jsonObj["icon"] = packageInfo[packageName]["icon"];
        jsonObj["ignored"] = false; // 默认不忽略
        
        // 如果有大小信息也加入
        if (packageInfo[packageName].contains("size")) {
            jsonObj["size"] = packageInfo[packageName]["size"];
        }
        
        // 在构建JSON对象时添加新字段（在jsonObj中添加）：
        if (packageInfo[packageName].contains("url")) {
            jsonObj["download_url"] = packageInfo[packageName]["url"];
            qDebug() << "生成的下载 URL:" << packageInfo[packageName]["url"]; // 检查生成的 URL
        } else {
            qWarning() << "未找到下载 URL，包名:" << packageName;
            jsonObj["download_url"] = ""; // 设置为空字符串以避免崩溃
        }
        jsonObj["sha512"] = packageInfo[packageName]["sha512"];
        jsonArray.append(jsonObj);
    }
    qDebug()<<jsonArray;
    return jsonArray;
}

QStringList aptssUpdater::getApmUpdateablePackages()
{
    QStringList packageDetails;
    
    // 检查apm命令是否存在
    QProcess checkProcess;
    checkProcess.start("which", QStringList() << "apm");
    if (!checkProcess.waitForFinished(5000) || checkProcess.exitCode() != 0) {
        qDebug() << "apm命令不存在，跳过APM更新检查";
        return packageDetails;
    }
    
    QProcess process;
    QString command = R"(env LANGUAGE=en_US /usr/bin/apm list --upgradable | awk 'NR>1')";
    
    process.start("bash", QStringList() << "-c" << command);
    if (!process.waitForFinished(30000)) { // 30秒超时
        qWarning() << "APM process failed to finish within 30 seconds.";
        process.kill();
        return packageDetails;
    }

    QString output = process.readAllStandardOutput();
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
        QStringList lines = output.split('\n', Qt::SkipEmptyParts);
#else
        QStringList lines = output.split('\n', QString::SkipEmptyParts);
#endif

    for (const QString &line : lines) {
        QRegularExpression regex(R"(([\w\-\+\.]+)/\S+\s+([^\s]+)\s+\S+\s+\[upgradable from: ([^\]]+)\])");
        QRegularExpressionMatch match = regex.match(line);
        if (match.hasMatch()) {
            QString name = match.captured(1);
            QString newVersion = match.captured(2);
            QString oldVersion = match.captured(3);
            
            // 检查版本是否相同，相同则跳过
            if (newVersion == oldVersion) {
                qDebug() << "跳过版本相同的APM包:" << name << "(" << oldVersion << "→" << newVersion << ")";
                continue;
            }
            
            // 写入内存列表
            packageDetails << QString("%1: %2 → %3").arg(name, oldVersion, newVersion);
        }
    }

    return packageDetails;
}

QJsonArray aptssUpdater::getApmUpdateInfoAsJson()
{
    QJsonArray jsonArray;
    
    // 解析APM包版本信息
    QHash<QString, QHash<QString, QString>> packageInfo;
    for (const QString &pkg : apmPackageName) {
        QStringList parts = pkg.split(": ");
        if (parts.size() >= 2) {
            QString packageName = parts[0];
            QStringList versions = parts[1].split(" → ");
            if (versions.size() == 2) {
                packageInfo[packageName]["current_version"] = versions[0];
                packageInfo[packageName]["new_version"] = versions[1];
                packageInfo[packageName]["source"] = "apm";
            }
        }
    }
    
    // 构建JSON数组
    for (const QString &packageName : packageInfo.keys()) {
        QJsonObject jsonObj;
        jsonObj["package"] = packageName;
        
        // 从APM桌面文件中解析应用名称和图标
        QString displayName = packageName; // 默认使用包名
        QString iconPath = ":/resources/default_icon.png"; // 默认图标
        
        // APM应用的desktop文件路径
        QString apmDesktopPath = QString("/var/lib/apm/apm/files/ace-env/var/lib/apm/%1/entries/applications").arg(packageName);
        QDir desktopDir(apmDesktopPath);
        if (desktopDir.exists()) {
            // 查找desktop文件
            QStringList desktopFiles = desktopDir.entryList(QStringList() << "*.desktop", QDir::Files);
            if (!desktopFiles.isEmpty()) {
                QString desktopFile = desktopDir.absoluteFilePath(desktopFiles.first());
                QFile file(desktopFile);
                if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
                    QTextStream in(&file);
                    while (!in.atEnd()) {
                        QString line = in.readLine().trimmed();
                        if (line.startsWith("Name=")) {
                            displayName = line.mid(5).trimmed();
                        } else if (line.startsWith("Icon=")) {
                            QString iconName = line.mid(5).trimmed();
                            // 处理图标路径
                            if (!iconName.contains('/')) {
                                // 查找APM包中的图标
                                QString apmIconPath = QString("/var/lib/apm/apm/files/ace-env/var/lib/apm/%1/entries/icons/hicolor/48x48/apps/%2.png").arg(packageName, iconName);
                                if (QFile::exists(apmIconPath)) {
                                    iconPath = apmIconPath;
                                }
                            } else {
                                // 已经是绝对路径
                                if (QFile::exists(iconName)) {
                                    iconPath = iconName;
                                }
                            }
                        }
                    }
                    file.close();
                }
            }
        }
        
        // 获取APM包大小和下载信息
        QString size = "0";
        QString url = "";
        QString sha512 = "";
        
        QProcess process;
        QString command = QString("amber-pm-debug /usr/bin/apt -c /opt/durapps/spark-store/bin/apt-fast-conf/aptss-apt.conf download %1 --print-uris").arg(packageName);
        
        process.start("bash", QStringList() << "-c" << command);
        if (process.waitForFinished(30000)) { // 30秒超时
            QString output = process.readAllStandardOutput();
            // 解析输出格式：'URL' 文件名 大小 SHA512:哈希值
            QRegularExpression regex(R"('([^']+)'\s+\S+\s+(\d+)\s+SHA512:([^\s]+))");
            QRegularExpressionMatch match = regex.match(output);
            
            if (match.hasMatch()) {
                url = match.captured(1);
                size = match.captured(2);
                sha512 = match.captured(3);
            }
        }
        
        jsonObj["name"] = displayName;
        jsonObj["current_version"] = packageInfo[packageName]["current_version"];
        jsonObj["new_version"] = packageInfo[packageName]["new_version"];
        jsonObj["icon"] = iconPath;
        jsonObj["ignored"] = false; // 默认不忽略
        jsonObj["source"] = "apm";
        jsonObj["size"] = size;
        jsonObj["download_url"] = url;
        jsonObj["sha512"] = sha512;
        jsonArray.append(jsonObj);
    }
    qDebug()<<"APM更新信息:"<<jsonArray;
    return jsonArray;
}

QJsonArray aptssUpdater::mergeUpdateInfo()
{
    QJsonArray aptssInfo = getUpdateInfoAsJson();
    QJsonArray apmInfo = getApmUpdateInfoAsJson();

    // 创建包名到更新信息的映射
    QHash<QString, QJsonObject> aptssMap;
    for (const QJsonValue &value : aptssInfo) {
        QJsonObject obj = value.toObject();
        QString packageName = obj["package"].toString();
        obj["source"] = "aptss";
        aptssMap[packageName] = obj;
    }

    QHash<QString, QJsonObject> apmMap;
    for (const QJsonValue &value : apmInfo) {
        QJsonObject obj = value.toObject();
        QString packageName = obj["package"].toString();
        obj["source"] = "apm";
        apmMap[packageName] = obj;
    }

    QJsonArray mergedArray;

    // 处理只在aptss中存在的包
    for (const QString &packageName : aptssMap.keys()) {
        if (!apmMap.contains(packageName)) {
            mergedArray.append(aptssMap[packageName]);
        }
    }

    // 处理只在apm中存在的包
    for (const QString &packageName : apmMap.keys()) {
        if (!aptssMap.contains(packageName)) {
            mergedArray.append(apmMap[packageName]);
        }
    }

    // 处理在两者中都存在的包
    for (const QString &packageName : aptssMap.keys()) {
        if (apmMap.contains(packageName)) {
            QJsonObject aptssObj = aptssMap[packageName];
            QJsonObject apmObj = apmMap[packageName];

            // 比较版本
            QString aptssVersion = aptssObj["new_version"].toString();
            QString apmVersion = apmObj["new_version"].toString();

            // 检查包在两个源中的安装状态
            bool installedInAptss = isPackageInstalledInAptss(packageName);
            bool installedInApm = isPackageInstalledInApm(packageName);

            // 判断是否为迁移场景：
            // 1. 只在 aptss 中安装了包（不在 apm 中安装）
            // 2. APM 版本更新
            if (installedInAptss && !installedInApm && apmVersion > aptssVersion) {
                // 迁移场景：Spark -> APM
                QJsonObject migrationObj = apmObj;
                migrationObj["is_migration"] = true;
                migrationObj["migration_source"] = "aptss";
                migrationObj["migration_target"] = "apm";
                migrationObj["aptss_version"] = aptssVersion;
                mergedArray.append(migrationObj);

                // 同时保留aptss的更新项（如果aptss也有更新）
                mergedArray.append(aptssObj);
            } else {
                // 非迁移场景（共存场景）：同时展示两个来源的更新
                // 包括以下情况：
                // 1. 同时在 aptss 和 apm 中都安装了包
                // 2. 只在 apm 中安装了包
                // 3. APM 版本不更新
                mergedArray.append(aptssObj);
                mergedArray.append(apmObj);
            }
        }
    }

    qDebug()<<"合并后的更新信息:"<<mergedArray;
    return mergedArray;
}

bool aptssUpdater::isPackageInstalledInAptss(const QString &packageName)
{
    QProcess process;
    QString command = QString("dpkg -s '%1' 2>/dev/null | grep -q 'Status: install ok installed'").arg(packageName);
    process.start("bash", QStringList() << "-c" << command);
    if (!process.waitForFinished(5000)) {
        process.kill();
        return false;
    }
    return process.exitCode() == 0;
}

bool aptssUpdater::isPackageInstalledInApm(const QString &packageName)
{
    QProcess process;
    process.start("apm", QStringList() << "list" << "--installed");
    if (!process.waitForFinished(30000)) {
        process.kill();
        return false;
    }
    QString output = process.readAllStandardOutput();
    // 解析格式: pkgname/repo,section version arch [flags]
    // 或: pkgname/repo version arch [flags]
    QRegularExpression regex(QString("^%1/\\S+(?:,\\S+)?\\s+\\S+\\s+\\S+\\s+\\[").arg(QRegularExpression::escape(packageName)));
    return regex.match(output).hasMatch();
}
