/*
 * Copyright (c) KylinSoft  Co., Ltd. 2024. All rights reserved.
 *
 * kaiming is licensed under the GPL v2.0+.
 *
 * See the LICENSE file for more details.
 */

#include <sys/ioctl.h>
#include <unistd.h>
#include <thread>
#include <atomic>
#include <string>
#include <iostream>
#include <sstream>
#include <dlfcn.h>
#include <sys/file.h>
#include <fcntl.h>
#include <dirent.h>

#include "KMPackageManager.h"
// #include "common/KMFileLock.h"

#include "common/KMLogger.h"
#include "common/KMInstalledAppQuery.h"
#include "common/KMDbusJson.h"
#include "common/KMVersion.h"
#include "common/KMStringUtils.h"
#include "common/KMFileUtils.h"
#include "common/KMLibHandle.h"
#include "common/KMDirMd5sum.h"
#include "common/KMPluginSynchronizer.h"
#include "app/list/KMList.h"

#define TEST_ONLINE 1

static vector<KMPMRef> g_refDownloadListForProgress;             // 实际上需要安装的软件列表,用于进度展示
static KMPMProgressCallBack globalProgressCallback;              // 回调函数
static KMPMProgressStatus globalProgressStatus = {"", 0, "", 5}; // 安装进度回调函数参数
string progressJson = "";

string lastOutput;             // 保存最后一次进度条输出
string preRemaining = "";      // 保存先前的剩余时间
static int currentPercent = 0; // 当前进度

static int lastWidth = 0;
static std::string lastProgressStr;
static std::string lastStaticInfo;
static bool staticInfoDisplayed = false;
static bool installing = false;

std::atomic<int> sharedValue(0);             // 定义一个原子类型的共享变量，初始值为0
constexpr int SUMMARY_EXPIRE_SECONDS = 3600; // the expire check time of summary

class KMPackageManager::Private
{
public:
    std::unique_ptr<KMFolder> m_folder;
    std::unique_ptr<KMList> m_list;
    std::unique_ptr<KMUtil> m_util;
    std::unique_ptr<KMEnv> m_env;
    std::unique_ptr<KMParseSummaryJson> m_parseSummaryJson; // 解析 summary.json
    std::unique_ptr<KMFormatter> m_formatter;               // 格式化输出
    bool m_pmIsForceInstall = false;                        // 是否强制安装
    bool m_pmIsThereDbusService = true;                     // 是否有dbus安装卸载检测服务
    bool m_isHostapp = false;                               // 是否是hostapp
    bool m_isOffInstall = false;                            // 是否是离线安装
    KMPMRef m_pmRef;                                        // 单独ref,用于存储到 d->m_refUserList中
    std::vector<KMPMRef> m_pmRefDownloadList;               // 实际上需要安装的软件列表
    std::vector<KMPMRef> m_pmRefOfflineList;                // 实际上需要安装的软件列表
    std::vector<std::string> m_pmFuzzyMatchRefs;            // 从依赖文件中模糊匹配到的 ref 列表
    std::vector<KMRef> m_pmQueryVector;                     // 本地指定信息安装列表
    std::vector<KMRef> m_pmUninstallVector;                 // 卸载列表
    std::vector<std::string> m_pmOldAVersion;               // 旧版本app
    std::vector<std::string> m_pmSpecialIdVersion;          // 特殊版本app
    std::vector<std::string> m_pmReserveDepend;             // 保留depend依赖
    std::map<std::string, KMPMRef> m_pmRefMap;              // 存储所有ref的map表
    std::map<std::string, std::string> m_installedInfo;     // 存储所有已安装的开明包信息
    std::set<std::string> m_installedFiles;                 // 存储所有已安装的文件列表
    std::vector<std::string> m_pmDownloadRefs;              // 先遍历运行时，再遍历app。因此先压入app,之后提取的时候顺序不会乱
    std::vector<KMfilterInfo> m_upgragableList;             // 可更新的列表
    std::vector<std::string> m_pmCanNotInstallVector;       // 不可以安装的包名
    std::multimap<std::string, std::string> m_pmOkBase;     // 离线包所需的在线依赖
    std::vector<std::string> m_pmInstallId;                 // 安装软件包名
    std::map<std::string, KMRef> m_mapRefs;                 // ref映射表
    std::vector<std::string> m_pmBinName;
    std::shared_ptr<KMOSTreeHandler> m_ostreeHandler;
    std::unique_ptr<KMOKFile> m_okFile;               // ok 文件解压
    std::shared_ptr<KMOABMetadata> m_okMetadata;      // ok 文件解压中的 metadata 数据
    std::unique_ptr<KMHostAppDeploy> m_hostAppDeploy; // hostapp deploy
};

KMPackageManager::KMPackageManager()
    : d(std::make_unique<Private>())
{
    initializeFixedModifications();
    d->m_folder = std::make_unique<KMFolder>(KAIMING_SYSTEM_PATH, false);
    d->m_util = std::make_unique<KMUtil>();
    d->m_env = std::make_unique<KMEnv>();
    d->m_parseSummaryJson = std::make_unique<KMParseSummaryJson>();
    d->m_formatter = std::make_unique<KMFormatter>();

    d->m_ostreeHandler = std::make_unique<KMOSTreeHandler>(d->m_folder->getRepoPath()); // opt/kaiming/repo
    d->m_okFile = std::make_unique<KMOKFile>();                                         // ok 文件解压
    d->m_okMetadata = std::make_shared<KMOABMetadata>();                                // ok 文件解压中的 metadata 数据
    d->m_hostAppDeploy = std::make_unique<KMHostAppDeploy>(d->m_folder->getInfoPath());
    d->m_list = std::make_unique<KMList>();
    d->m_mapRefs = d->m_ostreeHandler->getLocalRefs(BASE_REOMTE);
}

KMPackageManager::~KMPackageManager()
{
}

int KMPackageManager::processTask(TaskType taskType, const vector<string> &vectorIds, PackageManagerOptions pmOptions)
{
    // 环境校验
    if (!d->m_env->passEnvCheck())
    {
        kmlogger.error("Failed to check environments!");
        return KM_ERROR_CHECK_ENV_FAILED;
    }

    d->m_folder->ensureRepoForSudo(false);

    // KMFileLock pkgLock;
    // if (!pkgLock.lock(KMFileLock::LockType::WRITE)) {
    //     std::cerr << "Unable to acquire the kaiming lock, another process is already in progress!" << std::endl;
    //     return KM_ERROR_INSTALLING;
    // }

    int ret = 0;
    // 根据任务类型执行不同的任务
    switch (taskType)
    {
    case TaskType::TASK_TYPE_INSTALL:
        ret = install(vectorIds, pmOptions);
        break;

    case TaskType::TASK_TYPE_UPDATE:
        ret = update(vectorIds, pmOptions);
        break;

    case TaskType::TASK_TYPE_SEARCH:
        ret = search(vectorIds[0], pmOptions);
        break;

    case TaskType::TASK_TYPE_UNINSTALL:
        ret = uninstall(vectorIds, pmOptions);
        break;

    case TaskType::TASK_TYPE_REPAIR:
        ret = repair(vectorIds, pmOptions);
        break;

    case TaskType::TASK_TYPE_UPGRADE:
        ret = install(vectorIds, pmOptions);
        break;
    default:
        break;
    }

    return ret;
}

int KMPackageManager::install(const vector<string> &vectorIds, PackageManagerOptions pmOptions)
{
    if (pmOptions.isPrint)
    {
        std::cout << _("Search matching packages ...") << std::endl;
    }

    d->m_pmOldAVersion.clear();
    d->m_pmSpecialIdVersion.clear();
    d->m_pmInstallId.clear();
    d->m_pmCanNotInstallVector.clear();
    d->m_pmFuzzyMatchRefs.clear();

    d->m_pmIsForceInstall = pmOptions.force;
    int countOfflinePackages = 0;
    for (auto name : vectorIds)
    {
        kmlogger.info("Install app %s", name.c_str());
        bool isMatchedRefFlag = false;

        KMPMRef pmRef = d->m_util->parseKMPMRef(name);
        d->m_util->printKMPMRef(name, pmRef);

        // 如果用户指定了 arch，则覆盖默认的 arch
        if (!pmOptions.arch.empty())
        {
            pmRef.ref.arch = pmOptions.arch;
        }

        if (!pmOptions.kind.empty())
        {
            pmRef.ref.kind = pmOptions.kind;
        }

        if (pmRef.refSourceType == KMPACKAGE_SOURCE_TYPE_OK)
        {
            // 开始处理离线包
            ++countOfflinePackages;
        }
    }

    if (countOfflinePackages != 0 && countOfflinePackages != vectorIds.size())
    {
        cout << _("Please check the package is all online package or offline package!") << endl;
        return KM_ERROR_INSTALL_FAILED;
    }

    if (countOfflinePackages != 0)
    {
        // // 暂时先只安装一个离线包，之后优化
        // if (vectorIds.size() > 1)
        // {
        //     cout << _("Only support one offline package!") << endl;
        //     return KM_ERROR_INSTALL_FAILED;
        // }
        int ret = installOfflinePackage(vectorIds, pmOptions);
        if (!d->m_pmCanNotInstallVector.empty())
        {
            return KM_ERROR_NOT_INSTALL_ALLPACKAGE;
        }
        else
        {
            return ret;
        }
    }

    // 下载和解析清单依赖文件 summary.json
    string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
    fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";

    int getSummaryState = getRemoteSummary(summaryUrl.string(), false);
    if (getSummaryState != KM_ERROR_NO)
    {
        kmlogger.error("Get and parse summary.json file error!");
        return getSummaryState;
    }

    // 遍历取得所有符合条件的依赖列表
    int getFuzzyMatchState = getAllFuzzyMatchRefVector(vectorIds, pmOptions, TaskType::TASK_TYPE_INSTALL);
    if (getFuzzyMatchState != KM_ERROR_NO)
    {
        kmlogger.error("Get fuzzy match ref error!");
        return getFuzzyMatchState;
    }

    // 获取必要安装列表
    getUsefulRefList();
    // 获取真正安装列表
    getDownloadRefList(TaskType::TASK_TYPE_INSTALL);

    if (d->m_pmRefDownloadList.empty())
    {
        return KM_ERROR_ALREADY_INSTALLED;
    }

    // 展示下载列表信息
    printDownloadRefList(d->m_pmRefDownloadList);

    // 用户选择是否展示信息
    if (!printAssumeYesChoice(pmOptions))
    {
        return KM_ERROR_NOT_INSTALLED;
    };

    // 检测当前网址是否可以访问
    if (KMStringUtils::contains(ostreeRepoUrl, "http"))
    {
        if (KMCurl::checkURL(ostreeRepoUrl, 3))
        {
            kmlogger.debug("URL is accessible!");
        }
        else
        {
            kmlogger.error("Failed to access URL!");
            return KM_ERROR_CURL_CHECK_URL_FAILED;
        }
    }

    // 下载包
    int pullFlag = false;

    // pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmDownloadRefs, progressCallback);

    installing = true;  // 先设置安装标志
    std::thread([this]() {
        while (installing) {
            checkAndHandleNetwork(d->m_ostreeHandler);
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
    }).detach();  // 启动监控线程

    // 开始真正的拉取
    pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmDownloadRefs, progressCallback);

    installing = false; // 安装结束，停止监控

    if (!pullFlag)
    {
        return KM_ERROR_PULL_FAILED;
    }

    for (auto &ref : d->m_pmOldAVersion)
    {
        removeSpecificDeployFiles(ref);
        if (!d->m_pmIsForceInstall)
        {
            deleteSpecificRefsFromRepo(ref);
        }

        KMEntry entry = cutRef(ref);
        removePackageInfoFromList(entry.id, entry.version, entry.arch, entry.module);

        if (entry.kind == "app")
        {
            killAppid(entry.id);
        }
    }

    if (!pmOptions.skipSignatureVerification)
    {
        int verifyResult = KM_ERROR_NO;
        for (auto &downloadRef : d->m_pmRefDownloadList)
        {
            fs::path tmpPath = fs::path("/tmp/kaiming-tmp-deploy");
            if (!fs::exists(tmpPath))
            {
                fs::create_directory(tmpPath);
            }

            pullFromOstree(tmpPath, downloadRef);

            fs::path idPath = tmpPath / downloadRef.ref.id;
            // 验签
            verifyResult = verifySignature(downloadRef.ref.id, downloadRef.ref.kind, idPath);

            if (!removeTmpDeployFiles(downloadRef.ref.id, tmpPath))
            {
                kmlogger.info("删除临时目录失败");
            }
        }

        if (verifyResult != KM_ERROR_NO)
        {
            return verifyResult;
        }
        else
        {
            // 部署包
            int ret =  deploy();
            if (!d->m_pmCanNotInstallVector.empty())
            {
                return KM_ERROR_NOT_INSTALL_ALLPACKAGE;
            }
            else
            {
                return ret;
            }
        }
    }
    else
    {
        kmlogger.info("用户不进行验签，跳过验签步骤");
        // 部署包
        int ret =  deploy();

        if (!d->m_pmCanNotInstallVector.empty())
        {
            return KM_ERROR_NOT_INSTALL_ALLPACKAGE;
        }
        else
        {
            return ret;
        }
    }
}

int KMPackageManager::installOfflinePackage(const vector<string> &vectorIds, PackageManagerOptions pmOptions)
{
    vector<string> onlinePackageIds; // 离线包的 id 列表
    std::map<string, string> mountMap;
    int ret = KM_ERROR_NO;
    bool printLog = false;
    bool canNotInstall = false;
    bool isVerifyFailed = false;

    d->m_okFile->clearMountPoint();
    d->m_pmRefOfflineList.clear();
    d->m_pmOkBase.clear();
    d->m_pmOldAVersion.clear();
    d->m_pmSpecialIdVersion.clear();
    d->m_pmInstallId.clear();
    d->m_pmCanNotInstallVector.clear();
    d->m_pmFuzzyMatchRefs.clear();

    for (auto name : vectorIds)
    {
        kmlogger.debug("Install offline packages %s", name.c_str());
        bool isMatchedRefFlag = false;

        KMPMRef pmRef = d->m_util->parseKMPMRef(name);
        d->m_util->printKMPMRef(name, pmRef);

        // 如果用户指定了 arch，则覆盖默认的 arch
        if (!pmOptions.arch.empty())
        {
            pmRef.ref.arch = pmOptions.arch;
        }

        if (!pmOptions.kind.empty())
        {
            pmRef.ref.kind = pmOptions.kind;
        }

        if (pmRef.refSourceType == KMPACKAGE_SOURCE_TYPE_OK)
        {
            d->m_isOffInstall = true;
            // 开始处理离线包
            ret = installFromOK(name, onlinePackageIds, pmOptions, mountMap, canNotInstall);

            if (ret != KM_ERROR_NO)
            {
                canNotInstall = true;
                continue;
            }
        }
    }

    if (!d->m_pmFuzzyMatchRefs.empty())
    {
        for (const auto &ref : d->m_pmFuzzyMatchRefs)
        {
            kmlogger.debug("fuzzy match ref : %s", ref.c_str());
        }

        // 依赖列表去重
        KMUtil::removeDuplicateValues(d->m_pmFuzzyMatchRefs);
    }
    else
    {
        if ((printLog || canNotInstall))
        {
            d->m_okFile->umountOK();
            return ret;
        }
        else
        {
            printf("%s\n", _("This app has been installed!"));
            d->m_okFile->umountOK();
            return KM_ERROR_ALREADY_INSTALLED;
        }
    }

    for (auto it = onlinePackageIds.begin(); it != onlinePackageIds.end();)
    {
        string onlinId = *it;
        KMPMRef idRef = d->m_util->parseKMPMRef(onlinId);
        bool isMatchedRefFlag = false;
        for (auto ref : d->m_pmFuzzyMatchRefs)
        {
            KMPMRef fuzzyRef = d->m_util->parseKMPMRef(ref);
            if (idRef.ref.id == fuzzyRef.ref.id && idRef.ref.kind == fuzzyRef.ref.kind && idRef.ref.arch == fuzzyRef.ref.arch && idRef.ref.module == fuzzyRef.ref.module && idRef.ref.channel == fuzzyRef.ref.channel)
            {
                if (idRef.ref.version[0] == '-')
                {
                    it = onlinePackageIds.erase(it);
                    isMatchedRefFlag = true;
                    break;
                }
                KMVersion idVersion = KMVersion::parse(idRef.ref.version, false);
                KMVersion fuzzyVersion = KMVersion::parse(fuzzyRef.ref.version, false);
                if (idVersion.getMajor() == fuzzyVersion.getMajor())
                {
                    it = onlinePackageIds.erase(it);
                    isMatchedRefFlag = true;
                    break;
                }
            }
        }
        if (!isMatchedRefFlag)
        {
            it++;
        }
    }

    string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
    fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";

    if (!onlinePackageIds.empty())
    {
        d->m_pmFuzzyMatchRefs.clear();
        int getSummaryState = getRemoteSummary(summaryUrl.string(), false);
        if (getSummaryState != KM_ERROR_NO)
        {
            kmlogger.error("Get and parse summary.json file error!");
            d->m_okFile->umountOK();
            return getSummaryState;
        }

        pmOptions.compatible = true;
        int getFuzzyMatchState = getAllFuzzyMatchRefVector(onlinePackageIds, pmOptions, TaskType::TASK_TYPE_INSTALL);

        if (!d->m_pmCanNotInstallVector.empty())
        {
            std::cout << _("The dependencies of these software packages cannot be satisfied: ") << std::endl;
        }

        for (auto notInstall : d->m_pmCanNotInstallVector)
        {
            std::unordered_set<std::string> keysToDelete;
            // 找出所有依赖 notInstall 的键
            for (auto it = d->m_pmOkBase.begin(); it != d->m_pmOkBase.end(); ++it)
            {
                if (it->second == notInstall)
                {
                    keysToDelete.insert(it->first);
                }
            }

            // 从 m_pmOkBase 中删除所有相关的键值对
            for (const auto &key : keysToDelete)
            {
                auto range = d->m_pmOkBase.equal_range(key);
                for (auto it = range.first; it != range.second; ++it)
                {
                    std::regex pattern(R"(([^/]+)/([^/]+)/([^/]+)/([^/]+)/([^/]+))");

                    for (auto itRef = d->m_pmFuzzyMatchRefs.begin(); itRef != d->m_pmFuzzyMatchRefs.end();)
                    {
                        KMPMRef pmFuzzyRef = KMUtil::parseSummaryFuzzyKMPMRef(*itRef);
                        std::smatch match;

                        if (std::regex_search(it->second, match, pattern))
                        {
                            std::string id = match[1].str();
                            std::string version = match[2].str();
                            std::string module = match[3].str();
                            std::string channel = match[4].str();
                            std::string arch = match[5].str();

                            if (pmFuzzyRef.ref.id == id && pmFuzzyRef.ref.module == module && pmFuzzyRef.ref.channel == channel && pmFuzzyRef.ref.arch == arch)
                            {
                                if (version != "-")
                                {
                                    KMVersion pmVersion = KMVersion::parse(pmFuzzyRef.ref.version, false);
                                    KMVersion reVersion = KMVersion::parse(version, false);
                                    if (pmVersion.getMajor() == reVersion.getMajor())
                                    {
                                        itRef = d->m_pmFuzzyMatchRefs.erase(itRef);
                                        continue;
                                    }
                                }
                                else
                                {
                                    itRef = d->m_pmFuzzyMatchRefs.erase(itRef);
                                    continue;
                                }
                            }
                        }
                        ++itRef;
                    }
                }
                std::cout << key << std::endl;
                d->m_pmOkBase.erase(key);
                printLog = true;
                // 从 m_pmRefOfflineList 中删除相关的引用
                auto newEnd = std::remove_if(d->m_pmRefOfflineList.begin(), d->m_pmRefOfflineList.end(), [this, key](const KMPMRef &element)
                                             { return element.ref.id == key; });
                d->m_pmRefOfflineList.erase(newEnd, d->m_pmRefOfflineList.end());
            }
        }

        if (getFuzzyMatchState != KM_ERROR_NO)
        {
            d->m_okFile->umountOK();
            kmlogger.error("Get fuzzy match ref error!");
            return getFuzzyMatchState;
        }

        // 获取必要安装列表
        getUsefulRefList();
        // 获取真正安装列表
        getDownloadRefList(TaskType::TASK_TYPE_INSTALL);
    }

    d->m_isOffInstall = false;

    if (d->m_pmRefOfflineList.empty() && d->m_pmRefDownloadList.empty())
    {
        if (printLog || canNotInstall)
        {
            d->m_okFile->umountOK();
            return KM_ERROR_NOT_INSTALLED;
        }
        else
        {
            printf("%s\n", _("This app has been installed!"));
            d->m_okFile->umountOK();
            return KM_ERROR_ALREADY_INSTALLED;
        }
    }
    else if (d->m_pmRefOfflineList.empty() && !d->m_pmRefDownloadList.empty())
    {
        // 展示下载列表信息
        printDownloadRefList(d->m_pmRefDownloadList);

        // 用户选择是否展示信息
        if (!printAssumeYesChoice(pmOptions))
        {
            d->m_okFile->umountOK();
            return KM_ERROR_NOT_INSTALLED;
        }

        // 检测当前网址是否可以访问
        if (KMStringUtils::contains(ostreeRepoUrl, "http"))
        {
            if (KMCurl::checkURL(ostreeRepoUrl, 3))
            {
                kmlogger.debug("URL is accessible!");
            }
            else
            {
                kmlogger.error("Failed to access URL!");
                d->m_okFile->umountOK();
                return KM_ERROR_CURL_CHECK_URL_FAILED;
            }
        }

        // 下载包
        int pullFlag = false;
        // pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmDownloadRefs, progressCallback);

        installing = true;  // 先设置安装标志
        std::thread([this]() {
            while (installing) {
                checkAndHandleNetwork(d->m_ostreeHandler); 
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
            }
        }).detach();  // 启动监控线程

        // 开始真正的拉取
        pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmDownloadRefs, progressCallback);

        installing = false; // 安装结束，停止监控
        
        if (!pullFlag)
        {
            d->m_okFile->umountOK();
            return KM_ERROR_PULL_FAILED;
        }

        // 部署在线下载包
        kmlogger.info("Only deploy online package!");

        for (auto &ref : d->m_pmOldAVersion)
        {
            removeSpecificDeployFiles(ref);
            if (!d->m_pmIsForceInstall)
            {
                deleteSpecificRefsFromRepo(ref);
            }
            KMEntry entry = cutRef(ref);
            removePackageInfoFromList(entry.id, entry.version, entry.arch, entry.module);

            if (entry.kind == "app")
            {
                killAppid(entry.id);
            }
        }

        return deploy();
    }
    else if (!d->m_pmRefOfflineList.empty() && d->m_pmRefDownloadList.empty())
    {
        // 展示下载列表信息
        printDownloadRefList(d->m_pmRefOfflineList);

        // 用户选择是否展示信息
        if (!printAssumeYesChoice(pmOptions))
        {
            d->m_okFile->umountOK();
            return KM_ERROR_NOT_INSTALLED;
        }

        // 部署离线包
        kmlogger.info("Only deploy offline package!");

        for (auto &ref : d->m_pmOldAVersion)
        {
            removeHostAppDeployFiles(ref, TaskType::TASK_TYPE_UPGRADE);
            removeSpecificDeployFiles(ref);
            if (!d->m_pmIsForceInstall)
            {
                deleteSpecificRefsFromRepo(ref);
            }
            KMEntry entry = cutRef(ref);
            removePackageInfoFromList(entry.id, entry.version, entry.arch, entry.module);

            if (entry.kind == "app")
            {
                killAppid(entry.id);
            }
        }

        return deployOfflinePackage(mountMap);
    }
    else
    {
        // 展示下载列表信息
        vector<KMPMRef> allRefList;
        allRefList.insert(allRefList.end(), d->m_pmRefOfflineList.begin(), d->m_pmRefOfflineList.end());
        allRefList.insert(allRefList.end(), d->m_pmRefDownloadList.begin(), d->m_pmRefDownloadList.end());
        printDownloadRefList(allRefList);

        for (auto &offline : d->m_pmRefOfflineList)
        {
            kmlogger.info("offline ref: %s\n", offline.completedRef.c_str());
        }

        for (auto &online : d->m_pmRefDownloadList)
        {
            kmlogger.info("online ref: %s\n", online.completedRef.c_str());
        }

        // 用户选择是否展示信息
        if (!printAssumeYesChoice(pmOptions))
        {
            d->m_okFile->umountOK();
            return KM_ERROR_NOT_INSTALLED;
        }

        // 部署离线包
        kmlogger.info("Deploy offline package!");

        // 检测当前网址是否可以访问
        if (KMStringUtils::contains(ostreeRepoUrl, "http"))
        {
            if (KMCurl::checkURL(ostreeRepoUrl, 3))
            {
                kmlogger.debug("URL is accessible!");
            }
            else
            {
                kmlogger.error("Failed to access URL!");
                return KM_ERROR_CURL_CHECK_URL_FAILED;
            }
        }

        // 下载包
        int pullFlag = false;
        // pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmDownloadRefs, progressCallback);
        installing = true;  // 先设置安装标志
        std::thread([this]() {
            while (installing) {
                checkAndHandleNetwork(d->m_ostreeHandler);
                std::this_thread::sleep_for(std::chrono::milliseconds(500));
            }
        }).detach();  // 启动监控线程

        // 开始真正的拉取
        pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmDownloadRefs, progressCallback);

        installing = false; // 安装结束，停止监控
        
        if (!pullFlag)
        {
            return KM_ERROR_PULL_FAILED;
        }

        // 部署在线下载包
        kmlogger.info("Deploy online package!");
        int retDeploy = deploy();
        if (retDeploy != KM_ERROR_NO)
        {
            return retDeploy;
        }

        for (auto &ref : d->m_pmOldAVersion)
        {
            removeSpecificDeployFiles(ref);
            if (!d->m_pmIsForceInstall)
            {
                deleteSpecificRefsFromRepo(ref);
            }
            KMEntry entry = cutRef(ref);
            removePackageInfoFromList(entry.id, entry.version, entry.arch, entry.module);

            if (entry.kind == "app")
            {
                killAppid(entry.id);
            }
        }

        return deployOfflinePackage(mountMap);
    }
}

int KMPackageManager::installSoftwareCenter(const string &name, string version, KMPMProgressCallBack installCallback, std::vector<std::string> &refs)
{
    kmlogger.debug("begin install");
    globalProgressCallback = installCallback;

    int ret = KM_ERROR_NOTHING_TO_DO;

    PackageManagerOptions pmOption;
    vector<string> vecInstall;

    pmOption.assumeYes = true;
    pmOption.skipSignatureVerification = false;

    vecInstall.push_back(name);

    ret = install(vecInstall, pmOption);

    if (!d->m_pmCanNotInstallVector.empty())
    {
        for (auto notInstall : d->m_pmCanNotInstallVector)
        {
            refs.push_back(notInstall);
        }
    }

    kmlogger.debug("end install");
    return ret;
}

int KMPackageManager::updateSoftwareCenter(const string &name, string version, KMPMProgressCallBack updateCallback)
{
    kmlogger.debug("begin update");
    globalProgressCallback = updateCallback;

    int ret = KM_ERROR_NOTHING_TO_DO;

    PackageManagerOptions pmOption;
    vector<string> vecUpdate;

    pmOption.assumeYes = true;
    vecUpdate.push_back(name);

    ret = update(vecUpdate, pmOption);

    kmlogger.debug("end update");
    return ret;
}

int KMPackageManager::uninstallSoftwareCenter(const std::string &name)
{
    kmlogger.debug("begin uninstall");

    int ret = KM_ERROR_NOTHING_TO_DO;

    PackageManagerOptions pmOption;
    vector<string> vecUninstall;

    pmOption.assumeYes = true;
    vecUninstall.push_back(name);

    ret = uninstall(vecUninstall, pmOption);

    kmlogger.debug("end uninstall");
    return ret;
}

int KMPackageManager::installFromOK(const string &name, vector<string> &onlinePackageIds, PackageManagerOptions pmOptions, std::map<string, string> &mountMap, bool &canNotInstall)
{
    d->m_okMetadata->layers.clear();
    size_t pos = name.find(".ok");
    string mountPoint = "/tmp/" + name.substr(0, pos) + "_" + std::to_string(getpid());

    d->m_okFile->setMountPoint(mountPoint);
    // d->m_okFile->setOKFilePath(name);

    if (!d->m_okFile->loadOKFile(name))
    {
        std::cout << "Failed to load file: " << name << std::endl;
        return KM_ERROR_LOAD_FILE_FAILED;
    }

    d->m_okFile->mountOK(mountPoint);
    d->m_okMetadata = d->m_okFile->getMetadata();
    std::vector<KMInfoJson> layers = d->m_okMetadata->layers;

    if (!pmOptions.skipSignatureVerification)
    {
        std::string filename = name.substr(0, pos);
        size_t lastSlashPos = filename.find_last_of("/\\");
        filename = (lastSlashPos != std::string::npos) ? filename.substr(lastSlashPos + 1) : filename;
        std::string okId, okKind, okModule;

        if (layers.size() == 1)
        {
            okId = layers[0].id;
            okKind = layers[0].kind;
            okModule = layers[0].module;
        }
        std::string path = mountPoint + "/" + "layers/" + okId + "/" + okModule;
        fs::path modulePath = path;
        int errorCode = verifySignature(okId, okKind, modulePath);

        if (errorCode != KM_ERROR_NO)
        {
            return KM_ERROR_SIGN_FAILED;
        }
    }

    if (layers.empty())
    {
        kmlogger.error("No layers found in OK file!");
        std::cout << "No layers found in OK file! " << name << std::endl;
        return KM_ERROR_NO_LAYERS_FOUND;
    }

    vector<std::string> preVersion;
    if (layers.size() == 1)
    {
        for (auto layer : layers)
        {
            KMPMRef pmRef;
            string base = layer.base;
            string runtime = layer.runtime;
            vector<string> depends = layer.annotations.depends;

            if (layer.annotations.deltas == true)
            {
                preVersion = layer.annotations.preVersion;
            }

            pmRef.ref.preVersion = preVersion;
            pmRef.ref.isDeltas = layer.annotations.deltas;
            pmRef.ref.id = layer.id;
            pmRef.ref.channel = layer.channel;
            pmRef.ref.version = layer.version;
            pmRef.ref.module = layer.module;
            pmRef.ref.kind = layer.kind;
            pmRef.installedSize = layer.size;
            pmRef.name = layer.name;
            pmRef.description = layer.description;
            pmRef.ref.isSysapp = layer.annotations.sysapp;
            mountMap[layer.id + layer.module] = mountPoint;
            pmRef.ref.isHostapp = layer.getAnnotations().hostapp;
            pmRef.ref.vecPlugins = layer.export_plugins;

            if (d->m_pmIsThereDbusService)
            {
                const char *dbusmethod = "GetPackageInstallStatus";
                const char *idChar = pmRef.ref.id.c_str();
                const char *dbusInterface = "com.kylin.kysdk.applicationsec.antiinstall";
                int getDbusReturn = d->m_parseSummaryJson->getDbus(dbusInterface, dbusmethod, idChar);

                if (getDbusReturn == -1)
                {
                    d->m_pmIsThereDbusService = false;
                }
                if (getDbusReturn == 1)
                {
                    canNotInstall = true;
                    std::cout << "can not install " << pmRef.ref.id << std::endl;
                    return KM_ERROR_INSTALL_FAILED;
                }
            }

            for (auto arch : layer.archs)
            {
                if (arch == KMUtil::kmGetArch())
                {
                    pmRef.ref.arch = arch;
                }
                else if (KMUtil::kmGetArch() == "longarch64" && arch == "long64")
                {
                    pmRef.ref.arch = arch;
                }
            }

            if (pmRef.ref.arch.empty() && (layer.kind == "base" || layer.kind == "runtime"))
            {
                pmRef.ref.arch = layer.archs[0];
            }

            pmRef.completedRef = KMUtil::dupKMPMCompletedRef(pmRef);
            d->m_pmRefMap[layer.id] = pmRef;

            if (pmRef.ref.arch.empty())
            {
                const std::string &filePath = d->m_okFile->getOKFilePath();
                std::cout << "Unsupported architecture for file: " << filePath << std::endl;
                kmlogger.error("Unsupported architecture - File: %s", filePath.c_str());
                return KM_ERROR_NOT_SUPPORT_ARCH;
            }
            pmRef.ref.isSpecialVersion = true;
            d->m_pmSpecialIdVersion.push_back(pmRef.ref.id + pmRef.ref.version);

            if (currentFuzzyRefIsInstalled(pmRef))
            {
                // 不强制安装已经安装的应用
                if (!pmOptions.force)
                {
                    std::cout << _("This package has been installed! ") << pmRef.ref.id << std::endl;
                    return KM_ERROR_NOT_UNINSTALLED;
                }

                std::string removeStr;

                if (pmRef.ref.module == "binary")
                {
                    fs::path rootPath = d->m_folder->getLayersPath();
                    removeStr = rootPath.string() + "/" + pmRef.completedRef;
                }

                if (pmRef.ref.module == "devel")
                {
                    fs::path develDir = fs::path(KMStorageDir::getUserBaseDirLocation());
                    removeStr = develDir.string() + "/" + pmRef.completedRef;
                }
                removeSpecificDeployFiles(removeStr);
            }

            for (auto version : pmRef.ref.preVersion)
            {
                for (auto it = d->m_pmOldAVersion.begin(); it != d->m_pmOldAVersion.end(); )
                {
                    const auto& oldVersion = *it;
                    size_t lastSlashPos = oldVersion.rfind('/');
                    if (lastSlashPos != std::string::npos) {
                        std::string nowOldVersion = oldVersion.substr(lastSlashPos + 1);
                        if (nowOldVersion == version)
                        {
                            pmRef.ref.findPreVersion = version;
                            it = d->m_pmOldAVersion.erase(it);
                            break;
                        }
                        else
                        {
                            ++it;
                        }
                    }
                    else
                    {
                        ++it;  // 无效路径，跳过
                    }
                }
                if (!pmRef.ref.findPreVersion.empty()) {
                    break;  // 如果已经找到预版本，跳出外层循环
                }
            }

            if (pmRef.ref.isDeltas)
            {
                if (pmRef.ref.findPreVersion.empty())
                {
                    std::cout << _("Not install preversion of: ") << pmRef.ref.id << std::endl;
                    return KM_ERROR_INSTALL_FAILED;
                }
                else
                {
                    std::string completedRef = pmRef.ref.id + "/" + pmRef.ref.version + "/" + pmRef.ref.module + "/" + pmRef.ref.channel + "/" + pmRef.ref.arch;
                    d->m_pmFuzzyMatchRefs.push_back(completedRef);
                    d->m_pmRefOfflineList.push_back(pmRef);
                    continue;
                }
            }

            std::string completedRef = pmRef.ref.id + "/" + pmRef.ref.version + "/" + pmRef.ref.module + "/" + pmRef.ref.channel + "/" + pmRef.ref.arch;
            d->m_pmFuzzyMatchRefs.push_back(completedRef);
            d->m_pmRefOfflineList.push_back(pmRef);

            if (pmRef.ref.kind != "base")
            {
                if (!runtime.empty())
                {
                    KMPMRef pmRuntimeRef = KMUtil::parseSummaryKMPMRef(runtime);
                    pmRuntimeRef.ref.module = layer.module;
                    std::string runtimeStr = pmRuntimeRef.ref.id + "/" + pmRuntimeRef.ref.version + "/" + layer.module + "/" + layer.channel + "/" + pmRef.ref.arch;

                    if (!d->m_parseSummaryJson->currentFuzzyRefIsInstalled(pmRuntimeRef))
                    {
                        d->m_pmOkBase.insert({pmRef.ref.id, runtimeStr});
                        onlinePackageIds.push_back(runtimeStr);
                    }
                }

                if (!base.empty())
                {
                    KMPMRef pmBaseRef = KMUtil::parseSummaryKMPMRef(base);
                    pmBaseRef.ref.module = layer.module;
                    std::string baseStr = pmBaseRef.ref.id + "/" + pmBaseRef.ref.version + "/" + layer.module + "/" + layer.channel + "/" + pmRef.ref.arch;
                    if (!d->m_parseSummaryJson->currentFuzzyRefIsInstalled(pmBaseRef))
                    {
                        d->m_pmOkBase.insert({pmRef.ref.id, baseStr});
                        onlinePackageIds.push_back(baseStr);
                    }
                }

                if (!depends.empty())
                {
                    for (std::string dependStr : depends)
                    {
                        KMPMRef pmDependRef;
                        std::vector<std::string> tokens;
                        std::stringstream ss(dependStr);
                        std::string token;
                        while (std::getline(ss, token, '/'))
                        {
                            tokens.push_back(token); // 将切分后的部分添加到 tokens 向量中
                        }

                        if (tokens.empty())
                        {
                            kmlogger.debug("Empty dependency string found: : %s", dependStr.c_str());
                            continue;
                        }

                        if (dependStr.find('/') != std::string::npos)
                        {
                            pmDependRef.ref.arch = pmRef.ref.arch;
                            pmDependRef.ref.id = tokens[0];
                            pmDependRef.ref.version = tokens.size() > 1 ? tokens[1] : "";
                            pmDependRef.ref.module = layer.module;
                            pmDependRef.ref.channel = layer.channel;

                            if (!d->m_parseSummaryJson->currentFuzzyRefIsInstalled(pmDependRef))
                            {
                                dependStr = dependStr + "/" + layer.module + "/" + layer.channel + "/" + pmRef.ref.arch;
                                d->m_pmOkBase.insert({pmRef.ref.id, dependStr});
                                onlinePackageIds.push_back(dependStr);
                            }
                        }
                        else
                        {
                            pmDependRef.ref.arch = pmRef.ref.arch;
                            pmDependRef.ref.id = tokens[0];
                            pmDependRef.ref.version = "";
                            pmDependRef.ref.module = layer.module;
                            pmDependRef.ref.channel = layer.channel;
                            if (!currentRefIsUninstalled(pmDependRef))
                            {
                                dependStr = dependStr + "/" + "-" + "/" + layer.module + "/" + layer.channel + "/" + pmRef.ref.arch;
                                d->m_pmOkBase.insert({pmRef.ref.id, dependStr});
                                onlinePackageIds.push_back(dependStr);
                            }
                        }
                    }
                }
            }
        }
    }
    else
    {
        for (auto layer : layers)
        {
            KMPMRef pmRef;
            string base = layer.base;
            string runtime = layer.runtime;

            pmRef.ref.id = layer.id;
            pmRef.ref.channel = layer.channel;
            pmRef.ref.version = layer.version;
            pmRef.ref.module = layer.module;
            pmRef.ref.kind = layer.kind;
            pmRef.installedSize = layer.size;
            pmRef.name = layer.name;
            pmRef.description = layer.description;

            for (auto arch : layer.archs)
            {
                if (arch == KMUtil::kmGetArch())
                {
                    pmRef.ref.arch = arch;
                }
            }

            if (d->m_pmIsThereDbusService)
            {
                const char *dbusmethod = "GetPackageInstallStatus";
                const char *idChar = pmRef.ref.id.c_str();
                const char *dbusInterface = "com.kylin.kysdk.applicationsec.antiinstall";
                int getDbusReturn = d->m_parseSummaryJson->getDbus(dbusInterface, dbusmethod, idChar);

                if (getDbusReturn == -1)
                {
                    d->m_pmIsThereDbusService = false;
                }
                if (getDbusReturn == 1)
                {
                    canNotInstall = true;
                    std::cout << "can not install " << pmRef.ref.id << std::endl;
                    return KM_ERROR_INSTALL_FAILED;
                }
            }

            pmRef.completedRef = KMUtil::dupKMPMCompletedRef(pmRef);

            if (pmRef.ref.arch.empty())
            {
                const std::string &filePath = d->m_okFile->getOKFilePath();
                std::cout << "Unsupported architecture for file: " << filePath << std::endl;
                kmlogger.error("Unsupported architecture - File: %s", filePath.c_str());
                return KM_ERROR_NOT_SUPPORT_ARCH;
            }

            if (currentRefIsInstalled(pmRef))
            {
                // 不强制安装已经安装的应用
                if (!pmOptions.force)
                {
                    return KM_ERROR_NOT_UNINSTALLED;
                }
            }
            d->m_pmRefOfflineList.push_back(pmRef);
        }
    }

    return KM_ERROR_NO;
}

int KMPackageManager::uninstall(const vector<string> &vectorIds, PackageManagerOptions pmOptions)
{
    std::vector<std::string> perUninstallList; // 待删除列表
    bool isUninstallable = true;
    vector<std::string> UninstallVector;
    vector<std::string> dependVector;

    d->m_pmReserveDepend.clear();
    // 遍历每个待卸载的应用ID
    for (auto name : vectorIds)
    {
        kmlogger.debug("Uninstall app %s", name.c_str());
        bool isMatchedRefFlag = false;

        KMPMRef pmRef = d->m_util->parseKMPMRef(name);
        d->m_util->printKMPMRef(name, pmRef);
        pmRef.ref.arch = pmOptions.arch;

        if (!currentRefIsUninstalled(pmRef))
        {
            kmlogger.pinfo("%s not installed!", name.c_str());
            continue;
        }
        // kmlogger.pinfo("find installed package %s", name.c_str());

        printUninstallList(pmRef);

        // 用户选择是否展示信息
        if (!printAssumeUninstallYesChoice(pmOptions, pmRef))
        {
            return KM_ERROR_NOT_UNINSTALLED;
        }

        bool needDevelMap = false;
        bool needRootMap = false;
        for (auto it : d->m_pmUninstallVector)
        {
            if (needDevelMap && needRootMap)
            {
                break;
            }
            if (it.module == "binary")
            {
                fs::path rootPath = d->m_folder->getLayersPath();
                std::unordered_map<std::string, KMInfoJson> rootMap = loadAllInfoJsonFiles(rootPath);
                m_infoMap.insert(rootMap.begin(), rootMap.end());
                needRootMap = true;
            }
            else
            {
                fs::path develDir = fs::path(KMStorageDir::getUserBaseDirLocation());
                std::unordered_map<std::string, KMInfoJson> develMap = loadAllInfoJsonFiles(develDir);
                m_infoMap.insert(develMap.begin(), develMap.end());
                needDevelMap = true;
            }
        }

        if (d->m_pmUninstallVector[0].kind == "app")
        {
            if (d->m_pmIsThereDbusService)
            {
                const char *dbusmethod = "GetPackageUninstallStatus";
                const char *idChar = d->m_pmUninstallVector[0].id.c_str();
                const char *dbusInterface = "com.kylin.kysdk.applicationsec.antiuninstall";
                int getDbusReturn = d->m_parseSummaryJson->getDbus(dbusInterface, dbusmethod, idChar);
                if (getDbusReturn == -1)
                {
                    d->m_pmIsThereDbusService = false;
                }

                if (getDbusReturn == 1)
                {
                    isUninstallable = false;
                    kmlogger.error("Can not uninstall %s", idChar);
                    std::cout << "Can not uninstall " << d->m_pmUninstallVector[0].id << std::endl;
                    return KM_ERROR_CANNOT_UNINSTALL;
                }
            }

            if (pmOptions.deletedataYes)
            {
                deleteUserData(name);
            }

            KMRef appRemoveRef = d->m_pmUninstallVector[0];
            removeUserDesktopShortcutsByMd5(appRemoveRef.id);
            deleteHostAppFiles(); // deleteHostAppFiles before removeDeployFiles

            string removeStr = appRemoveRef.baseInstallDir + "/" + appRemoveRef.channel + "/" + appRemoveRef.arch + "/" + appRemoveRef.kind + "/" + appRemoveRef.id + "/" + appRemoveRef.module + "/" + appRemoveRef.version;
            removeSpecificDeployFiles(removeStr);
            deleteSpecificRefsFromRepo(removeStr);

            killAppid(name);
            removePackageInfoFromList(appRemoveRef.id, appRemoveRef.version, appRemoveRef.arch, appRemoveRef.module);
        }

        vector<KMRef> unRemove = reserveVersion();

        if (d->m_pmUninstallVector[0].kind == "depend")
        {
            if (!unRemove.empty())
            {
                d->m_pmReserveDepend.push_back(unRemove[0].id);
            }

            for (auto &uninstallRef : d->m_pmUninstallVector)
            {
                bool isfound = false;
                for (auto reserveDepend : unRemove)
                {
                    KMVersion pmVersion = KMVersion::parse(reserveDepend.version, false);
                    KMVersion reVersion = KMVersion::parse(uninstallRef.version, false);
                    if (pmVersion.getMajor() == reVersion.getMajor())
                    {
                        isfound = true;
                        break;
                    }
                }

                if (isfound)
                {
                    std::string removeUninstallStr = uninstallRef.baseInstallDir + "/" + uninstallRef.channel + "/" + uninstallRef.arch + "/" + uninstallRef.kind + "/" + uninstallRef.id + "/" + uninstallRef.module + "/" + uninstallRef.version;
                    removeHostAppDeployFiles(removeUninstallStr); // remove hostapp first, need to read info.json
                    removeSpecificDeployFiles(removeUninstallStr);
                    deleteSpecificRefsFromRepo(removeUninstallStr);
                    continue;
                }

                if (!removeDepend(pmRef.ref.id, uninstallRef, UninstallVector))
                {

                    std::cout << "can not uninstall " << d->m_pmUninstallVector[0].id << std::endl;
                    break;
                }
            }

            printUninstallDependsOnList(UninstallVector);

            if (UninstallVector.empty() || isContinueUninstall())
            {
                for (auto &uninstallStr : UninstallVector)
                {
                    removeHostAppDeployFiles(uninstallStr); // remove hostapp first, need to read info.json
                    removeSpecificDeployFiles(uninstallStr);
                    deleteSpecificRefsFromRepo(uninstallStr);
                }
            }
        }

        if (d->m_pmUninstallVector[0].kind == "runtime" || d->m_pmUninstallVector[0].kind == "base")
        {

            for (auto it = d->m_pmUninstallVector.begin(); it != d->m_pmUninstallVector.end(); it++)
            {
                auto &uninstallIt = *it;
                for (auto &queryIt : unRemove)
                {
                    if (uninstallIt.arch == queryIt.arch && uninstallIt.channel == queryIt.channel && uninstallIt.module == queryIt.module)
                    {
                        if (uninstallIt.version != queryIt.version)
                        {
                            KMVersion uninstallVersion = KMVersion::parse(uninstallIt.version, false);
                            KMVersion queryVersion = KMVersion::parse(queryIt.version, false);
                            if (uninstallVersion.getMajor() == queryVersion.getMajor())
                            {
                                // directUninstallVector.push_back(uninstallIt);
                                std::string removeUninstallStr = uninstallIt.baseInstallDir + "/" + uninstallIt.channel + "/" + uninstallIt.arch + "/" + uninstallIt.kind + "/" + uninstallIt.id + "/" + uninstallIt.module + "/" + uninstallIt.version;
                                removeSpecificDeployFiles(removeUninstallStr);
                                deleteSpecificRefsFromRepo(removeUninstallStr);
                                it = d->m_pmUninstallVector.erase(it);
                                it--;
                                break;
                            }
                        }
                    }
                }
            }

            if (!d->m_pmUninstallVector.empty())
            {
                for (auto it = d->m_pmUninstallVector.begin(); it != d->m_pmUninstallVector.end(); it++)
                {
                    auto &uninstallIt = *it;

                    if (d->m_pmIsThereDbusService)
                    {
                        const char *dbusmethod = "GetPackageUninstallStatus";
                        const char *idChar = uninstallIt.id.c_str();
                        const char *dbusInterface = "com.kylin.kysdk.applicationsec.antiuninstall";
                        int getDbusReturn = d->m_parseSummaryJson->getDbus(dbusInterface, dbusmethod, idChar);

                        if (getDbusReturn == -1)
                        {
                            d->m_pmIsThereDbusService = false;
                        }
                        if (getDbusReturn == 1)
                        {
                            isUninstallable = false;
                            kmlogger.error("Can not uninstall %s", idChar);
                            std::cout << "can not uninstall " << uninstallIt.id << std::endl;
                            break;
                        }
                    }

                    KMVersion reVersion = KMVersion::parse(uninstallIt.version, false);
                    std::string removeUninstallStr = uninstallIt.baseInstallDir + "/" + uninstallIt.channel + "/" + uninstallIt.arch + "/" + uninstallIt.kind + "/" + uninstallIt.id + "/" + uninstallIt.module + "/" + uninstallIt.version;
                    std::string findStr = uninstallIt.channel + ":" + uninstallIt.id + "/" + std::to_string(reVersion.getMajor());
                    vector<std::string> willUninstallVector;

                    for (auto it = m_infoMap.begin(); it != m_infoMap.end();)
                    {
                        auto pair = *it;
                        KMInfoJson &info = pair.second;

                        if (info[uninstallIt.kind].find(findStr) != std::string::npos && info[uninstallIt.kind].find(uninstallIt.arch) != std::string::npos && info.module == uninstallIt.module)
                        {
                            if (d->m_pmIsThereDbusService)
                            {
                                const char *dbusmethod = "GetPackageUninstallStatus";
                                const char *idChar = info.id.c_str();
                                const char *dbusInterface = "com.kylin.kysdk.applicationsec.antiuninstall";
                                int getDbusReturn = d->m_parseSummaryJson->getDbus(dbusInterface, dbusmethod, idChar);

                                if (getDbusReturn == -1)
                                {
                                    d->m_pmIsThereDbusService = false;
                                }

                                if (getDbusReturn == 1)
                                {
                                    isUninstallable = false;
                                    kmlogger.error("Can not uninstall %s", idChar);
                                    std::cout << info.id << " depends on " << name << ",but " << info.id << " can not be uninstalled" << std::endl;
                                    break;
                                }
                            }

                            if (info.kind == "runtime")
                            {
                                KMVersion reVersion = KMVersion::parse(info.version, false);
                                std::string runtimeStr = info.channel + ":" + info.id + "/" + std::to_string(reVersion.getMajor());

                                for (auto secondIt = m_infoMap.begin(); secondIt != m_infoMap.end();)
                                {
                                    auto secondPair = *secondIt;
                                    KMInfoJson &secondInfo = secondPair.second;

                                    if (secondInfo[info.kind].find(runtimeStr) != std::string::npos && secondInfo[info.kind].find(uninstallIt.arch) != std::string::npos && secondInfo.module == uninstallIt.module)
                                    {
                                        if (d->m_pmIsThereDbusService)
                                        {
                                            const char *dbusmethod = "GetPackageUninstallStatus";
                                            const char *idChar = secondInfo.id.c_str();
                                            const char *dbusInterface = "com.kylin.kysdk.applicationsec.antiuninstall";
                                            int getDbusReturn = d->m_parseSummaryJson->getDbus(dbusInterface, dbusmethod, idChar);

                                            if (getDbusReturn == -1)
                                            {
                                                d->m_pmIsThereDbusService = false;
                                            }

                                            if (getDbusReturn == 1)
                                            {
                                                isUninstallable = false;
                                                kmlogger.error("Can not uninstall %s", idChar);
                                                std::cout << d->m_pmUninstallVector[0].id << " depends on " << name << ",but " << d->m_pmUninstallVector[0].id << " can not be uninstalled" << std::endl;
                                                break;
                                            }
                                        }

                                        std::string removeSecondStr = secondPair.first;
                                        willUninstallVector.push_back(removeSecondStr);
                                        secondIt = m_infoMap.erase(secondIt);
                                    }
                                    else
                                    {
                                        secondIt++;
                                    }
                                }

                                if (!isUninstallable)
                                {
                                    break;
                                }
                            }
                            if (info.kind == "depend")
                            {
                                KMRef dependRef;
                                dependRef.id = info.id;
                                dependRef.kind = info.kind;
                                dependRef.module = info.module;
                                dependRef.arch = d->m_pmUninstallVector[0].arch;
                                dependRef.version = info.version;
				dependRef.channel = info.channel;
                                dependRef.baseInstallDir = fs::path(KMStorageDir::getUserBaseDirLocation());
                                isUninstallable = removeDepend(pmRef.ref.id, dependRef, willUninstallVector);

                                if (!isUninstallable)
                                {
                                    break;
                                }
                            }
                            std::string removeStr = pair.first;
                            willUninstallVector.push_back(removeStr);
                            it = m_infoMap.erase(it);
                        }
                        else
                        {
                            it++;
                        }
                    }

                    if (!isUninstallable)
                    {
                        break;
                    }

                    UninstallVector.push_back(removeUninstallStr);
                    dependVector.insert(dependVector.end(), willUninstallVector.begin(), willUninstallVector.end());
                    UninstallVector.insert(UninstallVector.end(), willUninstallVector.begin(), willUninstallVector.end());
                }

		KMUtil::removeDuplicateValues(dependVector);
		KMUtil::removeDuplicateValues(UninstallVector);
                printUninstallDependsOnList(dependVector);

                if (dependVector.empty() || isContinueUninstall())
                {
                    for (auto &uninstallStr : UninstallVector)
                    {
                        removeHostAppDeployFiles(uninstallStr);
                        removeSpecificDeployFiles(uninstallStr);
                        deleteSpecificRefsFromRepo(uninstallStr);
                    }
                }
            }
        }
    }
    return KM_ERROR_NO;
}

bool KMPackageManager::removeDepend(const std::string &name, const KMRef &uninstallRef, std::vector<std::string> &UninstallVector)
{
    bool isUninstallable = true;
    if (d->m_pmIsThereDbusService)
    {
        const char *dbusmethod = "GetPackageUninstallStatus";
        const char *idChar = uninstallRef.id.c_str();
        const char *dbusInterface = "com.kylin.kysdk.applicationsec.antiuninstall";
        int getDbusReturn = d->m_parseSummaryJson->getDbus(dbusInterface, dbusmethod, idChar);

        if (getDbusReturn == -1)
        {
            d->m_pmIsThereDbusService = false;
        }
        if (getDbusReturn == 1)
        {
            isUninstallable = false;
            if (uninstallRef.id == name)
            {
                kmlogger.error("Can not uninstall %s", idChar);
                std::cout << "can not uninstall " << name << std::endl;
                return isUninstallable;
            }
            else
            {
                kmlogger.error("Can not uninstall %s", idChar);
                std::cout << uninstallRef.id << " depends on " << name << ", but " << uninstallRef.id << " can not be uninstalled" << std::endl;
            }
        }
    }

    std::string removeUninstallStr = uninstallRef.baseInstallDir + "/" + uninstallRef.channel + "/" + uninstallRef.arch + "/" + uninstallRef.kind + "/" + uninstallRef.id + "/" + uninstallRef.module + "/" + uninstallRef.version;
    auto it = std::find(UninstallVector.begin(), UninstallVector.end(), removeUninstallStr);

    if (it != UninstallVector.end())
    {
        return true;
    }
    else
    {
        UninstallVector.push_back(removeUninstallStr);
    }

    for (auto it = m_infoMap.begin(); it != m_infoMap.end();)
    {
        auto pair = *it;
        KMInfoJson &info = pair.second;
        std::string uninstallArch;
        auto uninstallArchIt = std::find(info.archs.begin(), info.archs.end(), uninstallRef.arch);

        if (uninstallArchIt != info.archs.end())
        {
            uninstallArch = uninstallRef.arch;
        }
        else
        {
            uninstallArch = info.archs[0];
        }

        if (uninstallArch != uninstallRef.arch || info.module != uninstallRef.module || info.channel != uninstallRef.channel)
        {
            it++;
            continue;
        }

        for (auto dependstr : info.annotations.depends)
        {
            if (dependstr.find(uninstallRef.id) != std::string::npos)
            {
                KMVersion uninstallVersion = KMVersion::parse(uninstallRef.version, false);
                uint64_t uninstallVersionStr = uninstallVersion.getMajor();
                std::string dependInfo = uninstallRef.id + "/" + std::to_string(uninstallVersionStr);
                KMRef dependRef;
                dependRef.id = info.id;
                dependRef.kind = info.kind;
                dependRef.module = info.module;
                dependRef.channel = info.channel;
                dependRef.arch = uninstallArch;
                dependRef.version = info.version;
                dependRef.baseInstallDir = fs::path(KMStorageDir::getUserBaseDirLocation());

                if (dependstr.find(dependInfo) != std::string::npos)
                {
                    if (!removeDepend(name, dependRef, UninstallVector))
                    {
                        isUninstallable = false;
                        return isUninstallable;
                    }
                }
                else
                {
                    if (!d->m_pmReserveDepend.empty())
                    {
                        for (auto reserver : d->m_pmReserveDepend)
                        {
                            if (reserver == uninstallRef.id)
                            {
                                d->m_pmReserveDepend.push_back(info.id);
                            }
                            else
                            {
                                if (!removeDepend(name, dependRef, UninstallVector))
                                {
                                    isUninstallable = false;
                                    return isUninstallable;
                                }
                            }
                        }
                    }
                    else
                    {
                        if (!removeDepend(name, dependRef, UninstallVector))
                        {
                            isUninstallable = false;
                            return isUninstallable;
                        }
                    }
                }
            }
        }
        it++;
    }

    return isUninstallable;
}

void KMPackageManager::killAppid(const std::string &appId)
{
    std::string loginUser = KMStorageDir::getLoginUser();
    std::string xdgRuntimeDir = KMStorageDir::getXdgRuntimeDir(loginUser);
    if (xdgRuntimeDir.empty())
    {
        kmlogger.error("Invalid parameters user=%s", loginUser.c_str());
        return;
    }

    std::string killCommand = "sudo -u " + loginUser + " XDG_RUNTIME_DIR=" + xdgRuntimeDir + " -- /opt/kaiming-tools/bin/kaiming kill " + appId + " >/dev/null 2>&1";
    FILE *pipe = popen(killCommand.c_str(), "r");
    if (!pipe)
    {
        kmlogger.error("Failed to execute command: %s", killCommand.c_str());
        return;
    }

    char buffer[128];
    std::string commandOutput;
    while (fgets(buffer, sizeof(buffer), pipe))
    {
        commandOutput += buffer;
    }

    int ret = pclose(pipe);
    if (ret != 0)
    {
        kmlogger.debug("kaiming kill failed (ret=%d): %s\nOutput: %s", ret, killCommand.c_str(), commandOutput.c_str());
    }
    else
    {
        kmlogger.info("kaiming kill succeeded: %s", killCommand.c_str());
    }
}

bool KMPackageManager::isContinueUninstall()
{
    bool isContinueUninstall = false;
    while (true)
    {
        std::cout << _("The apps, which depends on those packages, will be uninstalled, do you want to continue (Y or N)?");
        std::string input;
        std::getline(std::cin, input);

        // 检查是否输入 'a'
        if (input == "y" || input == "Y")
        {
            isContinueUninstall = true;
            return isContinueUninstall;
        }
        else if (input == "n" || input == "N")
        {
            return isContinueUninstall;
        }
        else
        {
            continue;
        }
    }
}

void KMPackageManager::printUninstallList(const KMPMRef &pmRef)
{
    // 初始化最大宽度
    size_t maxIdWidth = 0;
    size_t maxChannelWidth = 0;
    size_t maxArchWidth = 0;
    size_t maxModuleWidth = 0;
    size_t maxVersionWidth = 0;
 
    // 第一次遍历：计算最大宽度
    for (const auto &ref : d->m_pmQueryVector) 
    {
        // 如果指定了版本号且不匹配，则跳过
        if (!pmRef.ref.version.empty() && pmRef.ref.version != ref.version) 
        {
            continue;
        }
    
        maxIdWidth = std::max(maxIdWidth, ref.id.length());
        maxChannelWidth = std::max(maxChannelWidth, ref.channel.length());
        maxArchWidth = std::max(maxArchWidth, ref.arch.length());
        maxModuleWidth = std::max(maxModuleWidth, ref.module.length());
        maxVersionWidth = std::max(maxVersionWidth, ref.version.length());
    }
 
    // 设置最小宽度（确保不小于列标题）
    const size_t minIdWidth = 2;         // "ID" 标题长度
    const size_t minChannelWidth = 7;     // "Channel" 标题长度
    const size_t minArchWidth = 4;        // "Arch" 标题长度
    const size_t minModuleWidth = 6;      // "Module" 标题长度
    const size_t minVersionWidth = 7;     // "Version" 标题长度
 
    maxIdWidth = std::max(maxIdWidth, minIdWidth) + 5;
    maxChannelWidth = std::max(maxChannelWidth, minChannelWidth) + 5;
    maxArchWidth = std::max(maxArchWidth, minArchWidth) + 5;
    maxModuleWidth = std::max(maxModuleWidth, minModuleWidth) + 5;
    maxVersionWidth = std::max(maxVersionWidth, minVersionWidth) + 5;
 
    // 打印表头
    printf("\033[1;36m%-10s %-*s %-*s %-*s %-*s %-*s\033[0m\n",
         _("No."),  
         static_cast<int>(maxIdWidth), _("ID"),
         static_cast<int>(maxChannelWidth), _("Channel"),
         static_cast<int>(maxArchWidth), _("Arch"),
         static_cast<int>(maxModuleWidth), _("Module"),
         static_cast<int>(maxVersionWidth), _("Version"));

    // 第二次遍历：打印数据
    int i = 1;
    // printf("\n%-10s %-30s %-15s %-15s %-15s %-15s\n", _(" "), _("ID"), _("Channel"), _("Arch"), _("Module"), _("Version"));
    const bool filterByVersion = !pmRef.ref.version.empty();

    for (const auto &ref : d->m_pmQueryVector)
    {
        // 如果指定了版本号且不匹配，则跳过
        if (filterByVersion && pmRef.ref.version != ref.version)
        {
            continue;
        }

        // 打印行数据
        printf("%-10d %-*s %-*s %-*s %-*s %-*s\n", 
            i,
            static_cast<int>(maxIdWidth), ref.id.c_str(),
            static_cast<int>(maxChannelWidth), ref.channel.c_str(),
            static_cast<int>(maxArchWidth), ref.arch.c_str(),
            static_cast<int>(maxModuleWidth), ref.module.c_str(),
            static_cast<int>(maxVersionWidth), ref.version.c_str());
        i++;
    }
}

bool KMPackageManager::removeDeployFiles()
{
    std::set<std::string> allUniqueLines;

    for (auto &it : d->m_pmUninstallVector)
    {
        fs::path versionFile = it.baseInstallDir + "/" + it.channel + "/" + it.arch + "/" + it.kind + "/" + it.id + "/" + it.module + "/" + it.version;
        fs::path deployFile = versionFile / "deploy";

        if (!fs::exists(deployFile))
        {
            // std::cerr << "文件不存在: " << deployFile << std::endl; // 输出调试信息
            continue; // 跳过该文件
        }

        auto lines = KMFolder::readDeployFiles(deployFile);
        allUniqueLines.insert(lines.begin(), lines.end());
    }

    deleteFilesIfExist(allUniqueLines);
    removeEmptyDirs(allUniqueLines);

    return true;
}

void KMPackageManager::deleteHostAppFiles()
{
    for (auto &it : d->m_pmUninstallVector)
    {
        fs::path versionFile = it.baseInstallDir + "/" + it.channel + "/" + it.arch + "/" + it.kind + "/" + it.id + "/" + it.module + "/" + it.version;
        d->m_hostAppDeploy->setHostAppConfig(versionFile, it.id);
        if (d->m_hostAppDeploy->loadHostAppInfo())
        {
            d->m_hostAppDeploy->uninstall();
        }

        clearCacheFiles(it.id);

        const fs::path serviceDir = versionFile / "entries" / "etc" / "systemd" / "system" / "multi-user.target.wants";
        if (fs::exists(serviceDir))
        {
            for (const auto &entry : fs::directory_iterator(serviceDir))
            {
                if (entry.path().extension() == ".service")
                {
                    std::string serviceName = entry.path().stem().string();

                    std::string serviceCommand = "systemctl stop " + serviceName;
                    int ret = system(serviceCommand.c_str());
                    if (ret == 0)
                    {
                        kmlogger.info("Stopped service: %s", serviceName.c_str());
                    }
                    else
                    {
                        kmlogger.error("Failed to stop service: %s", serviceName.c_str());
                    }
                }
            }
        }
    }
}

void KMPackageManager::removeEmptyDirs(const std::set<std::string> &files)
{
    const std::set<std::string> protectedDirs = {
        "/opt/kaiming/share/applications",
        "/opt/kaiming/share/icons",
        "/opt/kaiming/exports/share/applications",
        "/opt/kaiming/exports/share/icons"};

    for (const auto &file : files)
    {
        fs::path dir = fs::path(file).parent_path();
        while (dir != "/" && fs::exists(dir))
        {
            if (protectedDirs.find(dir.string()) != protectedDirs.end())
            {
                break;
            }

            if (fs::is_empty(dir))
            {
                fs::remove(dir);
                KMDebug("Removed empty dir: " + dir.string());
                dir = dir.parent_path();
            }
            else
            {
                break;
            }
        }
    }
}

std::unordered_map<std::string, KMInfoJson> KMPackageManager::loadAllInfoJsonFiles(std::string pathStr)
{
    // fs::path layersPath = d->m_folder->getLayersPath();
    std::unordered_map<std::string, KMInfoJson> infoMap;

    // 遍历目录中的所有info.json文件
    try
    {
        for (const auto &dirEntry : std::filesystem::recursive_directory_iterator(pathStr))
        {
            if (dirEntry.is_regular_file() && dirEntry.path().filename() == "info.json")
            {
                auto filenameStr = dirEntry.path().string();
                KMInfoJson infoJson;
                infoJson.loadFile(filenameStr);

                size_t lastSlashPos = filenameStr.find_last_of('/');
                if (lastSlashPos != std::string::npos)
                {
                    filenameStr = filenameStr.substr(0, lastSlashPos);
                }
                // 使用文件路径作为key存储每个infoJson对象
                infoMap[filenameStr] = infoJson;
            }
        }
    }
    catch (const std::filesystem::filesystem_error &e)
    {
        std::cerr << e.what() << std::endl;
        kmlogger.perror(e.what());
    }

    return infoMap;
}

bool KMPackageManager::printAssumeUninstallYesChoice(const PackageManagerOptions &pmOptions, const KMPMRef &pmRef)
{
    d->m_pmUninstallVector.clear();

    std::vector<KMRef> speIndices;
    if (!pmRef.ref.version.empty())
    {
        for (const auto &ref : d->m_pmQueryVector)
        {
            if (pmRef.ref.version == ref.version)
            {
                speIndices.push_back(ref);
            }
        }

        if (speIndices.empty())
        {
            std::cout << pmRef.ref.id << " " << pmRef.ref.version << " not installed" << std::endl;
            return false;
        }
    }

    const auto &targetRefs = pmRef.ref.version.empty() ? d->m_pmQueryVector : speIndices;

    if (!pmOptions.assumeYes)
    {
        while (true)
        {
            // yesOption = std::cin.get();
            std::cout << _("Enter number to delete (separated by spaces) or 'y' to delete all, enter 'n' to cancel: ");
            d->m_pmUninstallVector.clear();
            std::string input;
            std::getline(std::cin, input);

            // 检查是否输入 'a'
            if (input == "y" || input == "Y")
            {
                d->m_pmUninstallVector = targetRefs;
                break;
            }

            if (input == "n" || input == "N")
            {
                return false;
            }

            std::istringstream iss(input);
            std::vector<int> indices;
            int index;
            bool isValid = true;

            if (input.empty())
            {
                std::cout << "Input is empty" << std::endl;
                continue;
            }

            for (char ch : input)
            {
                if (!std::isdigit(ch) && ch != ' ')
                {
                    std::cout << "Invalid idx: " << input << std::endl;
                    isValid = false;
                    break;
                }
            }

            if (!isValid)
            {
                continue;
            }

            while (iss >> index)
            {
                indices.push_back(index);
            }

            indices.erase(std::unique(indices.begin(), indices.end()), indices.end());

            for (int idx : indices)
            {
                if (idx > 0 && idx <= static_cast<int>(targetRefs.size()))
                {
                    d->m_pmUninstallVector.push_back(targetRefs[idx - 1]);
                }
                else
                {
                    std::cout << "Invalid index: " << idx << std::endl;
                    isValid = false;
                }
            }

            if (!isValid)
            {
                continue;
            }

            break;
        }
    }
    else
    {
        d->m_pmUninstallVector = targetRefs;
    }

    return !d->m_pmUninstallVector.empty();
}

vector<KMRef> KMPackageManager::reserveVersion()
{
    vector<KMRef> unRemove = d->m_pmQueryVector;
    for (auto &it : d->m_pmUninstallVector)
    {
        unRemove.erase(std::remove_if(unRemove.begin(), unRemove.end(), [&](const KMRef &nowIt)
                                      { return it.arch == nowIt.arch && it.module == nowIt.module && it.version == nowIt.version; }),
                       unRemove.end());
    }
    return unRemove;
}

bool KMPackageManager::removeDeployFiles(const std::string &name)
{
    std::vector<fs::path> idPaths;

    fs::path rootDir = d->m_folder->getLayersPath();
    fs::path develDir = fs::path(KMStorageDir::getUserBaseDirLocation());

    KMFolder::findIdPaths(rootDir, name, idPaths);
    if (fs::exists(develDir))
    {
        KMFolder::findIdPaths(develDir, name, idPaths);
    }
    if (idPaths.empty())
    {
        // std::cerr << "No ID paths found for ID: " << name << std::endl;
        return false;
    }

    std::cout << "ID paths found: " << std::endl;
    for (const auto &path : idPaths)
    {
        std::cout << "  " << path << std::endl;
    }

    // Step 2: Find deploy files in each ID path
    std::vector<fs::path> deployFiles;
    for (const auto &idPath : idPaths)
    {
        KMFolder::findDeployFiles(idPath, deployFiles);
    }

    if (deployFiles.empty())
    {
        std::cerr << "No deploy files found for ID: " << name << std::endl;
        return false;
    }

    std::cout << "Deploy files found: " << std::endl;
    for (const auto &file : deployFiles)
    {
        std::cout << "  " << file << std::endl;
    }

    // Step 3: Read deploy files and collect unique lines
    std::set<std::string> allUniqueLines;
    for (const auto &deployFile : deployFiles)
    {
        auto lines = KMFolder::readDeployFiles(deployFile);
        allUniqueLines.insert(lines.begin(), lines.end());
    }

    // Step 4: Output and delete unique lines
    deleteFilesIfExist(allUniqueLines);

    return true;
}

bool KMPackageManager::removeTmpDeployFiles(const std::string &name, const fs::path &rootDir)
{
    std::vector<fs::path> idPaths;

    fs::path develDir = fs::path(KMStorageDir::getUserBaseDirLocation());

    KMFolder::findTmpIdPaths(rootDir, name, idPaths);

    if (idPaths.empty())
    {
        kmlogger.info("No ID paths found for ID: %s", name.c_str());
        return false;
    }

    kmlogger.info("ID paths found:");
    for (const auto &path : idPaths)
    {
        kmlogger.info("  %s", path.c_str());
    }

    for (const auto &path : idPaths)
    {
        if (fs::exists(path))
        {
            kmlogger.info("Deleting: %s", path.c_str());
            fs::remove_all(path);
        }
    }

    return true;
}

bool KMPackageManager::removeSpecificDeployFiles(const std::string &str)
{
    std::set<std::string> allUniqueLines;
    fs::path versionFile = str + "/" + "deploy";

    if (!fs::exists(versionFile))
    {
        // std::cerr << "文件不存在: " << deployFile << std::endl; // 输出调试信息
        return false; // 跳过该文件
    }

    auto lines = KMFolder::readDeployFiles(versionFile);
    allUniqueLines.insert(lines.begin(), lines.end());

    deleteFilesIfExist(allUniqueLines);
    removeEmptyDirs(allUniqueLines);
    kmlogger.info("正在卸载 completedRef: %s", str.c_str());

    return true;
}

void KMPackageManager::deleteFilesIfExist(const std::set<std::string> &fileList)
{
    for (const auto &filePath : fileList)
    {
        try
        {
            if (fs::exists(filePath) || fs::is_symlink(filePath))
            {
                std::cout << "File exists: " << filePath << ". Deleting..." << std::endl;
                fs::remove_all(filePath);
            }
            else
            {
                // std::cout << "File does not exist: " << filePath << ". Skipping..." << std::endl;
            }
        }
        catch (const fs::filesystem_error &e)
        {
            std::cerr << "Error processing file: " << filePath << ". Error: " << e.what() << std::endl;
        }
    }
}

bool KMPackageManager::deleteRefsFromRepo(const std::string &name)
{
    // 从本地repo中删除引用
    for (auto pair : d->m_mapRefs)
    {
        if (pair.second.id == name)
        {
            string refString = pair.second.branch + "/" + pair.second.arch + "/" + pair.second.kind + "/" + pair.second.id + "/" + pair.second.module + "/" + pair.second.version;

            if (!d->m_ostreeHandler->deleteRefTag("", string("deploy/").append(refString)))
            {
                return false;
            }

            if (!d->m_ostreeHandler->deleteRefTag(BASE_REOMTE, refString)) // file:///opt/kaiming/repo/refs/remotes/kaiming-repo/stable/x86_64/app/top.openkylin.Music
            {
                return false;
            }

            if (!d->m_ostreeHandler->repoPrune())
            {
                return false;
            }
        }
    }
    return true;
}

bool KMPackageManager::deleteSpecificRefsFromRepo(const std::string &str)
{
    int count = 0;
    size_t pos = str.length(); // 从末尾开始
    std::string extractedStr;
    // 从后往前找第 6 个 '/'
    while (pos != 0)
    {
        pos--;
        if (str[pos] == '/')
        {
            count++;
            if (count == 6)
            {
                extractedStr = str.substr(pos + 1); // 返回第 6 个 '/' 之后的内容
            }
        }
    }

    // 从本地repo中删除引用
    for (auto pair : d->m_mapRefs)
    {
        string refString = pair.second.branch + "/" + pair.second.arch + "/" + pair.second.kind + "/" + pair.second.id + "/" + pair.second.module + "/" + pair.second.version;

        if (refString == extractedStr)
        {
            if (!d->m_ostreeHandler->deleteRefTag("", string("deploy/").append(refString)))
            {
                return false;
            }

            if (!d->m_ostreeHandler->deleteRefTag(BASE_REOMTE, refString)) // file:///opt/kaiming/repo/refs/remotes/kaiming-repo/stable/x86_64/app/top.openkylin.Music
            {
                return false;
            }

            if (!d->m_ostreeHandler->repoPrune())
            {
                return false;
            }
            break;
        }
    }

    return true;
}

bool KMPackageManager::deleteUserData(const std::string &name)
{
    printf("remove app %s user data dir.\n", name.c_str());

    if (!fs::remove_all(d->m_folder->getAppDataPath(name)))
    {
        kmlogger.error("uninstall %s error, can't delete the directory.", name.c_str());
        return false;
    }
    return true;
}

int KMPackageManager::update(const vector<string> &vectorIds, PackageManagerOptions pmOptions)
{
    // 下载和解析清单依赖文件 summary.json
    std::cout << _("Search matching packages ...") << std::endl;

    fs::path basePath = d->m_folder->getPath();
    fs::path summaryJsonPath = basePath / "summary.json";
    string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);

    // if (KMFileUtils::isFileExpired(summaryJsonPath.string(), SUMMARY_EXPIRE_SECONDS))

    fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";
    int getSummaryState = getRemoteSummary(summaryUrl.string(), true);

    if (getSummaryState != KM_ERROR_NO)
    {
        kmlogger.error("Get and parse summary.json file error!");
        return getSummaryState;
    }

    if (vectorIds.empty())
    {
        // 仅更新包依赖清单文件
        return KM_ERROR_NO;
    }

    // 遍历取得所有符合条件的依赖列表
    int getFuzzyMatchState = getAllFuzzyMatchRefVector(vectorIds, pmOptions, TaskType::TASK_TYPE_UPDATE);
    if (getFuzzyMatchState != KM_ERROR_NO)
    {
        kmlogger.error("Get fuzzy match ref error!");
        return getFuzzyMatchState;
    }
    getUsefulRefList();
    // 获取真正更新列表
    getDownloadRefList(TaskType::TASK_TYPE_UPDATE);

    if (d->m_pmRefDownloadList.empty())
    {
        printf("%s\n", _("Not need to update!"));
        return KM_ERROR_NOT_NEED_UPDATE;
    }

    // 展示下载列表信息
    printDownloadRefList(d->m_pmRefDownloadList);

    // 用户选择是否展示信息
    if (!printAssumeYesChoice(pmOptions))
    {
        return KM_ERROR_NOT_INSTALLED;
    };

    // 检测当前网址是否可以访问
    if (KMStringUtils::contains(ostreeRepoUrl, "http"))
    {
        if (KMCurl::checkURL(ostreeRepoUrl, 3))
        {
            kmlogger.debug("URL is accessible!");
        }
        else
        {
            kmlogger.error("Failed to access URL!");
            return KM_ERROR_CURL_CHECK_URL_FAILED;
        }
    }

    // 下载包
    int pullFlag = false;
    // pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmDownloadRefs, progressCallback);
    installing = true;  // 先设置安装标志
    std::thread([this]() {
        while (installing) {
            checkAndHandleNetwork(d->m_ostreeHandler);
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
    }).detach();  // 启动监控线程

    // 开始真正的拉取
    pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmDownloadRefs, progressCallback);

    installing = false; // 安装结束，停止监控
    
    if (!pullFlag)
    {
        return KM_ERROR_PULL_FAILED;
    }
    for (auto &ref : d->m_pmOldAVersion)
    {
        removeSpecificDeployFiles(ref);
        deleteSpecificRefsFromRepo(ref);
        KMEntry entry = cutRef(ref);
        removePackageInfoFromList(entry.id, entry.version, entry.arch, entry.module);

        if (entry.kind == "app")
        {
            killAppid(entry.id);
        }
    }
    // 部署包
    return deploy();
}

int KMPackageManager::filterIdsNotInRemote(PackageManagerOptions pmOptions)
{
    std::vector<KMlocalAppsInfo> localAppsInfo = d->m_list->getLocalAppIds(false);

    pmOptions.arch = KMUtil::kmGetArch();

    if (!pmOptions.upgradable)
    {
        string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
        fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";
        int getSummaryState = getRemoteSummary(summaryUrl.string(), true);
        if (getSummaryState != KM_ERROR_NO)
        {
            kmlogger.error("Get and parse summary.json file error!");
            return getSummaryState;
        }
    }
    else
    {
        fs::path basePath = d->m_folder->getPath();
        fs::path summaryJsonPath = basePath / "summary.json";
        d->m_parseSummaryJson->loadFile(summaryJsonPath);
    }

    for (const auto &app : localAppsInfo)
    {
        std::vector<std::string> completePath = d->m_parseSummaryJson->printSearchJson(app.id, pmOptions.arch, pmOptions.kind, app.module, pmOptions.isPrint, pmOptions.isGetDevel);

        if (!completePath.empty() && !completePath[0].empty())
        {
            kmlogger.info("Currently installed app %s , completePath is : %s", app.id.c_str(), completePath[0].c_str());

            std::vector<std::string> splitPath;
            std::istringstream iss(completePath[0]);
            std::string token;
            while (std::getline(iss, token, '/'))
            {
                if (!token.empty())
                {
                    splitPath.push_back(token);
                }
            }

            std::string remoteArch, remoteId, remoteVersion, remoteModule;
            if (splitPath.size() >= 8)
            {
                remoteArch = splitPath[1];
                remoteId = splitPath[3];
                remoteModule = splitPath[4];
                remoteVersion = splitPath[5];
            }

            KMVersion parseVersion = KMVersion::parse(remoteVersion, false);
            KMVersion appVersion = KMVersion::parse(app.version, false);
            if (!remoteId.empty() && appVersion < parseVersion)
            {
                d->m_upgragableList.push_back({remoteId, remoteVersion, remoteArch, remoteModule});
            }
        }
    }

    return KM_ERROR_NO;
}

std::vector<std::string> KMPackageManager::getUpgradeInfo(PackageManagerOptions pmOptions)
{
    std::vector<KMlocalAppsInfo> localAppsInfo = d->m_list->getLocalAppIds(false);
    pmOptions.arch = KMUtil::kmGetArch();
    vector<std::string> vectorIds;

    string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
    fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";
    int getSummaryState = getRemoteSummary(summaryUrl.string(), true);
    if (getSummaryState != KM_ERROR_NO)
    {
        kmlogger.error("Get and parse summary.json file error!");
    }

    for (const auto &apps : localAppsInfo)
    {
        // 下载和解析清单依赖文件 summary.json
        pmOptions.isGetDevel = true;
        pmOptions.isPrint = false;
        std::vector<std::string> completePath = d->m_parseSummaryJson->printSearchJson(apps.id, pmOptions.arch, pmOptions.kind, apps.module, pmOptions.isPrint, pmOptions.isGetDevel);
        
        if (!completePath.empty() && !completePath[0].empty())
        {
            kmlogger.info("Currently installed app %s, completePath is: %s", apps.id.c_str(), completePath[0].c_str());
            std::vector<std::string> splitPath;
            std::istringstream iss(completePath[0]);
            std::string token;
            while (std::getline(iss, token, '/'))
            {
                if (!token.empty())
                {
                    splitPath.push_back(token);
                }
            }

            std::string remoteId, remoteVersion, remoModule;
            if (splitPath.size() >= 8)
            {
                remoteId = splitPath[3];
                remoteVersion = splitPath[5];
                remoModule = splitPath[4];
            }

            if (!remoteVersion.empty() && !apps.version.empty())
            {
                KMVersion parseVersion = KMVersion::parse(remoteVersion, false);
                KMVersion appVersion = KMVersion::parse(apps.version, false);
                if (!remoteId.empty() && appVersion < parseVersion)
                {
                    vectorIds.push_back(remoteId + "/" + remoteVersion + "/" + remoModule);
                }
            }
        } 
        else
        {    
            kmlogger.info("App %s has no complete path despite success", apps.id.c_str());
        }

    }
    return vectorIds;
}

int KMPackageManager::getUpgradableList(const std::vector<KMlocalAppsInfo> &localAppsInfo, PackageManagerOptions pmOptions)
{
    if (!pmOptions.upgradable)
    {
        // 环境校验
        if (!d->m_env->passEnvCheck())
        {
            kmlogger.error("Failed to check environments!");
            return KM_ERROR_CHECK_ENV_FAILED;
        }

        d->m_folder->ensureRepoForSudo(false);
    }

    std::vector<std::string> vectorIds;
    for (const auto &apps : localAppsInfo)
    {
        vectorIds.push_back(apps.id);
    }

    fs::path basePath = d->m_folder->getPath();

    std::vector<KMlocalAppsInfo> localInfo = localAppsInfo;
    int errorCode = filterIdsNotInRemote(pmOptions);
    if (errorCode != KM_ERROR_NO)
    {
        return errorCode;
    }
    else
    {
        if (!pmOptions.upgradable)
        {
            std::cout << _("There are ") << d->m_upgragableList.size() << _(" packages available for upgrade. Please run 'kaiming update --upgradable' to check them.") << std::endl;

            if (!d->m_upgragableList.empty())
            {
                fs::path cachePath = basePath / "cache";
                if (!fs::exists(cachePath))
                {
                    fs::create_directories(cachePath);
                }

                fs::path upgradablePath = cachePath / "upgradable.list";
                std::ofstream outfile(upgradablePath);

                if (outfile.is_open())
                {
                    for (const auto &vec : d->m_upgragableList)
                    {
                        kmlogger.info("%s is upgradable.", vec.id.c_str());
                        outfile << vec.id << ":" << vec.version << std::endl;
                    }
                    outfile.close();
                }
                else
                {
                    kmlogger.info("Failed to create %s", upgradablePath.string().c_str());
                    return KM_ERROR_CREATE_FILE_FAILED;
                }
            }
        }
        else
        {
            for (const auto &vec : d->m_upgragableList)
            {
                std::string version;

                auto it = std::find_if(localInfo.begin(), localInfo.end(),  
                [&](const KMlocalAppsInfo &info){  
                    return info.id == vec.id && info.module == vec.module;  
                });  

                if (it != localInfo.end()) 
                {
                    version = it->version;
                }
                std::cout << vec.id << " " << vec.version << " " << vec.arch << " " << vec.module << " [" << _("Can be upgraded from this version: ") << version << "]" << std::endl;
            }
        }
    }
    d->m_upgragableList.clear();
    return KM_ERROR_NO;
}

int KMPackageManager::dbusSearch(const string &strID, PackageManagerOptions pmOptions)
{
    GError *error = NULL;
    // 连接到 D-Bus 系统总线
    GDBusConnection *connection = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
    if (!connection)
    { // 连接失败
        kmlogger.error("Failed to connect to D-Bus: %s", error->message);
        g_clear_error(&error);
    }

    // 调用 getRemoteSummary 方法
    GVariant *result = g_dbus_connection_call_sync(
        connection,
        "org.kylin.kaiming",           // 服务名称
        "/org/kylin/kaiming",          // 对象路径
        "org.kylin.kaiming.interface", // 接口名称
        "getRemoteSummary",            // 方法名  与xml中的方法名一致
        NULL,                          // 传递给 getRemoteSummary 方法的参数
        // g_variant_new("(s)", vectorIds.c_str()), // 参数元组
        NULL, // 返回值类型（NULL 表示不检查）
        G_DBUS_CALL_FLAGS_NONE,
        -1,   // 超时时间,-1 表示默认超时
        NULL, // Cancellable
        &error);

    if (error)
    { // 调用失败
        kmlogger.error("Failed to call getRemoteSummary: %s", error->message);
        return KM_ERROR_CURL_DOWNLOAD_FAILED;
        g_clear_error(&error);
    }
    else
    {
        gboolean success;
        g_variant_get(result, "(b)", &success); // 假设返回值是布尔值
        kmlogger.debug("getRemoteSummary method call result: %s", success ? "Success" : "Failure");
        if (success == false)
        {
            std::cout << _("Please check your network connection!") << std::endl;
            return KM_ERROR_CURL_DOWNLOAD_FAILED;
        }
        g_variant_unref(result); // 释放资源
    }

    g_object_unref(connection); // 释放资源

    fs::path basePath = d->m_folder->getPath();
    fs::path summaryJsonPath = basePath / "summary.json";
    d->m_parseSummaryJson->loadFile(summaryJsonPath);
    d->m_parseSummaryJson->printSearchJson(strID, pmOptions.arch, pmOptions.kind, pmOptions.module, pmOptions.isPrint, pmOptions.isGetDevel);

    return KM_ERROR_NO;
}

int KMPackageManager::search(const string &strID, PackageManagerOptions pmOptions)
{
    std::cout << _("Search matching packages ...") << std::endl;
    fs::path basePath = d->m_folder->getPath();
    fs::path summaryJsonPath = basePath / "summary.json";

    if (KMFileUtils::isFileExpired(summaryJsonPath.string(), SUMMARY_EXPIRE_SECONDS))
    {
        string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
        fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";

        int getSummaryState = getRemoteSummary(summaryUrl.string(), true);
        if (getSummaryState != KM_ERROR_NO)
        {
            kmlogger.error("Get and parse summary.json file error!");
            return getSummaryState;
        }
    }

    d->m_parseSummaryJson->loadFile(summaryJsonPath.string());
    d->m_parseSummaryJson->printSearchJson(strID, pmOptions.arch, pmOptions.kind, pmOptions.module, pmOptions.isPrint, pmOptions.isGetDevel);

    return KM_ERROR_NO;
}

int KMPackageManager::searchInfo(const string &strID, PackageManagerOptions pmOptions, std::vector<std::string> &strCompletePath)
{
    if (pmOptions.isPrint)
    {
        std::cout << _("Search matching packages ...") << std::endl;
    }

    fs::path basePath = d->m_folder->getPath();
    fs::path summaryJsonPath = basePath / "summary.json";

    if (KMFileUtils::isFileExpired(summaryJsonPath.string(), SUMMARY_EXPIRE_SECONDS) || !d->m_util->isJsonFile(summaryJsonPath.string()))
    {
        string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
        fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";

        int getSummaryState = getRemoteSummary(summaryUrl.string(), true);
        if (getSummaryState != KM_ERROR_NO)
        {
            kmlogger.error("Get and parse summary.json file error!");
            return getSummaryState;
        }
    }
    else
    {
        d->m_parseSummaryJson->loadFile(summaryJsonPath.string()); // for system-dus restart load
    }

    pmOptions.arch = KMUtil::kmGetArch();
    strCompletePath = d->m_parseSummaryJson->printSearchJson(strID, pmOptions.arch, pmOptions.kind, pmOptions.module, pmOptions.isPrint, pmOptions.isGetDevel);

    return KM_ERROR_NO;
}

int KMPackageManager::getRemoteInfo(const std::string &name, std::string &strRemoteInfoJson, std::vector<std::string> &allRemoteInfoJson, std::string &remoteKind)
{
    PackageManagerOptions pmOptions;
    pmOptions.relativeRepoPath = "";
    pmOptions.isPrint = false;
    pmOptions.kind = remoteKind;
    pmOptions.arch = KMUtil::kmGetArch();

    std::vector<std::string> allRemoteInfo;
    int errorCode = searchInfo(name, pmOptions, allRemoteInfo);

    bool isSearchId = false;
    if (!allRemoteInfo.empty() && !allRemoteInfo[0].empty())
    {
        isSearchId = true;
    }

    if (isSearchId == false)
    {
        // 没有在summary.json中找到可匹配的id
        strRemoteInfoJson = KMDbusJson::errorRemoteJson();
        return KM_ERROR_REMOTE_NOT_FOUND;
    }

    if (errorCode != KM_ERROR_NO)
    {
        strRemoteInfoJson = KMDbusJson::errorRemoteJson();
    }
    else
    {
        if (!allRemoteInfo.empty())
        {
            for (auto &info : allRemoteInfo)
            {
                strRemoteInfoJson = KMDbusJson::parseRemotePathToJson(info);
                kmlogger.info("remoteInfoJson: %s", strRemoteInfoJson.c_str());
                allRemoteInfoJson.push_back(strRemoteInfoJson);
            }
        }
    }

    return errorCode;
}

int KMPackageManager::repair(const vector<string> &vectorIds, PackageManagerOptions pmOptions)
{
    vector<KMPMRef> installVector;

    for (auto name : vectorIds)
    {
        kmlogger.debug("Install app %s", name.c_str());
        bool isMatchedRefFlag = false;

        KMPMRef pmRef = d->m_util->parseKMPMRef(name);
        d->m_util->printKMPMRef(name, pmRef);

        // 如果用户指定了 arch，则覆盖默认的 arch
        if (!pmOptions.arch.empty())
        {
            pmRef.ref.arch = pmOptions.arch;
        }

        if (pmRef.refSourceType == KMPACKAGE_SOURCE_TYPE_OK)
        {
            return KM_ERROR_REPAIR_FAILED;
        }

        if (!currentRefIsUninstalled(pmRef))
        {
            std::cout << _("Not install") << name << std::endl;
        }
    }

    if (d->m_pmQueryVector.empty())
    {
        return KM_ERROR_REPAIR_FAILED;
    }
    // 完整的 ref ，如 "stable/x86_64/app/top.openkylin.Music/binary/2.0.0.0"

    // 进行损坏检测，过滤掉未损坏的应用
    auto it = d->m_pmQueryVector.begin();
    while (it != d->m_pmQueryVector.end())
    {
        KMRef ref = *(it);

        // 对修复的应用包files做md5判断，如果计算得到的md5与原md5一致则该包不损坏，跳过修复
        std::string layersPath = ref.baseInstallDir;

        std::string completedRef = ref.channel + '/' + ref.arch + '/' + ref.kind + '/' + ref.id + '/' + ref.module + '/' + ref.version;
        string removeStr = ref.baseInstallDir + "/" + completedRef;
        // 计算出files的md5
        std::string filesDirPath = KMStringUtils::buildFilename(layersPath, completedRef);
        std::string filesMd5 = KMStringUtils::buildFilename(filesDirPath, "files.md5");
        std::string filePrefix; // 读取出本地md5文件的值

        KMPMRef installRef;
        installRef.ref = ref;
        KMVersion reVersion = KMVersion::parse(ref.version, false);
        installRef.ref.version = (ref.kind == "app") ? "" : std::to_string(reVersion.getMajor());

        // 读取md5的文件不存在，该包存在修复列表中
        if (!fs::exists(filesMd5))
        {
            removeSpecificDeployFiles(removeStr);
            deleteSpecificRefsFromRepo(removeStr);
            installVector.push_back(installRef);
            removePackageInfoFromList(ref.id, ref.version, ref.arch, ref.module);
            ++it; // 迭代计算下一个文件
        }
        else
        {
            if (KMFileUtils::isObsolete(filesMd5))
            {
                std::string filesDirFiles = KMStringUtils::buildFilename(filesDirPath, "files");
                std::cout << _("Verify file MD5 checksum ") << ref.id << endl;
                std::string checksum = KMFileUtils::getDirMd5sum(filesDirFiles);

                // 读取之前判断md5是否存在
                KMFileUtils::readFile(filesMd5, filePrefix);

                // 如果本地的Md5的文件与计算出来的Md5文件相同，则该app/base/runtime则不需要修复
                if ((filePrefix == checksum) && (checksum != ""))
                {
                    it = d->m_pmQueryVector.erase(it); // 修复列表中移除当前app/base/runtime
                    std::cout << _("Repair") << ref.id << _("complete") << endl;
                }
                else
                {
                    installVector.push_back(installRef);
                    removeSpecificDeployFiles(removeStr);
                    deleteSpecificRefsFromRepo(removeStr);
                    removePackageInfoFromList(ref.id, ref.version, ref.arch, ref.module);
                    ++it; // 迭代计算下一个文件
                }
            }
            else
            {
                KMDirMd5sum md5sum(filesDirPath);
                if (md5sum.checksum("files"))
                {
                    it = d->m_pmQueryVector.erase(it); // 修复列表中移除当前app/base/runtime
                    std::cout << _("Repair") << ref.id << _("complete") << endl;
                }
                else
                {
                    installVector.push_back(installRef);
                    removeSpecificDeployFiles(removeStr);
                    deleteSpecificRefsFromRepo(removeStr);
                    removePackageInfoFromList(ref.id, ref.version, ref.arch, ref.module);
                    ++it; // 迭代计算下一个文件
                }
            }
        }
    }

    // 如果得到的修复list为空说明不需要修复则直接返回
    if (d->m_pmQueryVector.empty())
    {
        return KM_ERROR_NO;
    }

    fs::path repoPath = d->m_folder->getRepoPath(); // /opt/kaiming/repo
    string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
    std::string summaryUrl = ostreeRepoUrl.append("/").append("summary.json");
    fs::path basePath = d->m_folder->getPath();
    fs::path summaryJsonPath = basePath / "summary.json";
    bool isSummaryJsonExpired = KMFileUtils::isFileExpired(summaryJsonPath, 3600);
    int getSummaryState = getRemoteSummary(summaryUrl, isSummaryJsonExpired);

    if (getSummaryState != KM_ERROR_NO)
    {
        kmlogger.error("Get and parse summary.json file error!");
        return getSummaryState;
    }

    // 下载损坏文件
    for (auto findIt = installVector.begin(); findIt != installVector.end();)
    {
        KMPMRef pmRef = *findIt;
        vector<string> fuzzyMatchRefs;
        // 从远程依赖文件查找对应的包是否存在，并获取所有的依赖列表
        d->m_parseSummaryJson->fuzzyMatchCompletedRef(pmRef, fuzzyMatchRefs);
        string notInstallable = d->m_parseSummaryJson->getNotInstallable();
        vector<std::string> notFind = d->m_parseSummaryJson->getNotFind();

        if (!notInstallable.empty())
        {
            if (pmRef.ref.id == notInstallable)
            {
                std::cout << _("Can not install this package ") << pmRef.ref.id << std::endl;
            }
            else
            {
                std::cout << pmRef.ref.id << _(" Can not install the dependencies of this package:") << notInstallable << std::endl;
            }
            findIt = installVector.erase(findIt);
            d->m_parseSummaryJson->clearNotInstallable();
            continue;
        }

        if (!notFind.empty())
        {
            if (notFind[0] == pmRef.ref.id)
            {
                std::cout << _("Not find this online package ") << pmRef.ref.id << std::endl;
            }
            else
            {
                std::cout << pmRef.ref.id << _(" Can not find the dependencies of this package:") << std::endl;
                for (auto it : notFind)
                {
                    if (it == pmRef.ref.id)
                    {
                        continue;
                    }

                    std::cout << it << std::endl;
                }
            }
            findIt = installVector.erase(findIt);
            d->m_parseSummaryJson->clearNotInstallable();
            continue;
        }

        findIt++;
        d->m_pmFuzzyMatchRefs.insert(d->m_pmFuzzyMatchRefs.end(), fuzzyMatchRefs.begin(), fuzzyMatchRefs.end());
    }

    KMUtil::removeDuplicateValues(d->m_pmFuzzyMatchRefs);
    // 获取必要安装列表
    getUsefulRefList();

    for (auto &ref : d->m_pmFuzzyMatchRefs)
    {
        KMPMRef pmFuzzyRef = KMUtil::parseSummaryFuzzyKMPMRef(ref);
        pmFuzzyRef.completedRef = KMUtil::dupKMPMCompletedRef(pmFuzzyRef);
        // d->m_pmDownloadRefs.clear();
        d->m_pmDownloadRefs.push_back(pmFuzzyRef.completedRef);
        d->m_parseSummaryJson->getSummaryInfo(pmFuzzyRef);
        d->m_pmRefDownloadList.push_back(pmFuzzyRef);
        g_refDownloadListForProgress.push_back(pmFuzzyRef);
    }

    if (KMStringUtils::contains(ostreeRepoUrl, "http"))
    {
        if (KMCurl::checkURL(ostreeRepoUrl, 3))
        {
            kmlogger.debug("URL is accessible!");
        }
        else
        {
            kmlogger.error("Failed to access URL!");
            return KM_ERROR_CURL_CHECK_URL_FAILED;
        }
    }

    // 下载包
    int pullFlag = false;
    // pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmFuzzyMatchRefs, progressCallback);

    installing = true;  // 先设置安装标志
    std::thread([this]() {
        while (installing) {
            checkAndHandleNetwork(d->m_ostreeHandler);
            std::this_thread::sleep_for(std::chrono::milliseconds(500));
        }
    }).detach();  // 启动监控线程

    // 开始真正的拉取
    pullFlag = d->m_ostreeHandler->pull(REPO_NAME, d->m_pmFuzzyMatchRefs, progressCallback);

    installing = false; // 安装结束，停止监控
    
    if (!pullFlag)
    {
        return KM_ERROR_PULL_FAILED;
    }

    // 部署包
    deploy();
    for (const auto &name : vectorIds)
    {
        printf("Repair  %s complete", name.c_str());
    }
    return KM_ERROR_NO;
}

bool KMPackageManager::currentRefIsInstalled(KMPMRef &pmRef)
{
    KMInstalledAppQuery query;
    bool isInstalled = false;
    std::vector<KMRef> queryVector;
    string kindStr = pmRef.ref.kind.empty() ? "" : pmRef.ref.kind;
    string versionStr = pmRef.ref.version.empty() ? "" : pmRef.ref.version;
    string channelStr = pmRef.ref.channel.empty() ? "" : pmRef.ref.channel;
    string archStr = pmRef.ref.arch.empty() ? "" : pmRef.ref.arch;
    string moduleStr = pmRef.ref.module.empty() ? "binary" : pmRef.ref.module;

    queryVector = query.kind(kindStr).id(pmRef.ref.id).arch(archStr).channel(channelStr).version(versionStr).module(moduleStr).query(KMInstalledAppQuery::All);

    KMVersion installedVersion;
    KMVersion currentVersion;

    if (!queryVector.empty())
    {
        if (versionStr.empty())
        {
            // 未指定版本，则认为已安装
            isInstalled = true;
        }
        else
        {
            currentVersion = KMVersion::parse(versionStr, false);

            // 指定版本，则检查是否已安装
            for (const auto &ref : queryVector)
            {
                installedVersion = KMVersion::parse(ref.version, false);
                if (installedVersion == currentVersion)
                {
                    isInstalled = true;
                    break;
                }
            }
        }
    }
    return isInstalled;
}

bool KMPackageManager::currentRefVersionIsInstalled(KMPMRef &pmRef)
{
    KMInstalledAppQuery query;
    bool isInstalled = false;
    std::vector<KMRef> queryVector;
    string kindStr = pmRef.ref.kind.empty() ? "" : pmRef.ref.kind;
    string versionStr = pmRef.ref.version.empty() ? "" : pmRef.ref.version;
    string channelStr = pmRef.ref.channel.empty() ? "" : pmRef.ref.channel;
    string archStr = pmRef.ref.arch.empty() ? "" : pmRef.ref.arch;
    string moduleStr = pmRef.ref.module.empty() ? "binary" : pmRef.ref.module;

    queryVector = query.kind(kindStr).id(pmRef.ref.id).arch(archStr).channel(channelStr).version(versionStr).module(moduleStr).query(KMInstalledAppQuery::All);

    KMVersion installedVersion;
    KMVersion currentVersion;

    if (!queryVector.empty())
    {
        if (versionStr.empty())
        {
            // 未指定版本，则认为已安装
            // isInstalled = true;
        }
        else
        {
            currentVersion = KMVersion::parse(versionStr, false);

            // 指定版本，则检查是否已安装
            for (const auto &ref : queryVector)
            {
                installedVersion = KMVersion::parse(ref.version, false);
                if (installedVersion == currentVersion)
                {
                    isInstalled = true;
                    break;
                }
            }
        }
    }
    return isInstalled;
}

bool KMPackageManager::currentRefIsUninstalled(KMPMRef &pmRef)
{
    KMInstalledAppQuery query;
    bool isInstalled = false;
    // std::vector<KMRef> queryVector;
    string kindStr = pmRef.ref.kind.empty() ? "" : pmRef.ref.kind;
    string versionStr = "";
    // string versionStr = pmRef.ref.version.empty() ? "" : pmRef.ref.version;
    string channelStr = pmRef.ref.channel.empty() ? "" : pmRef.ref.channel;
    string moduleStr = pmRef.ref.module.empty() ? "" : pmRef.ref.module;
    string archStr = pmRef.ref.arch.empty() ? "" : pmRef.ref.arch;

    d->m_pmQueryVector = query.kind(kindStr).id(pmRef.ref.id).arch(archStr).channel(channelStr).version(versionStr).module(moduleStr).query(KMInstalledAppQuery::All);

    KMVersion installedVersion;
    KMVersion currentVersion;

    if (!d->m_pmQueryVector.empty())
    {
        if (versionStr.empty())
        {
            // 未指定版本，则认为已安装
            isInstalled = true;
        }
        else
        {
            currentVersion = KMVersion::parse(versionStr, false);

            // 指定版本，则检查是否已安装
            for (const auto &ref : d->m_pmQueryVector)
            {
                installedVersion = KMVersion::parse(ref.version, false);
                if (installedVersion == currentVersion)
                {
                    isInstalled = true;
                    break;
                }
            }
        }
    }
    return isInstalled;
}

bool KMPackageManager::currentFuzzyRefIsInstalled(KMPMRef &pmRef)
{
    KMInstalledAppQuery query;
    bool isInstalled = false;
    string kindStr = pmRef.ref.kind.empty() ? "" : pmRef.ref.kind;
    string versionStr = "";
    string channelStr = pmRef.ref.channel.empty() ? "" : pmRef.ref.channel;
    string moduleStr = pmRef.ref.module.empty() ? "binary" : pmRef.ref.module;
    string archStr = pmRef.ref.arch.empty() ? "" : pmRef.ref.arch;

    std::vector<KMRef> queryVector = query.kind(kindStr).id(pmRef.ref.id).arch(archStr).channel(channelStr).version(versionStr).module(moduleStr).query(KMInstalledAppQuery::All);

    KMVersion installedVersion;
    KMVersion currentVersion = KMVersion::parse(pmRef.ref.version, false);
    bool highVersion = false;

    if (!queryVector.empty())
    {
        // 指定版本，则检查是否已安装
        for (const auto &ref : queryVector)
        {
            installedVersion = KMVersion::parse(ref.version, false);
            std::string idVersion = pmRef.ref.id + pmRef.ref.version;
            auto it = std::find(d->m_pmSpecialIdVersion.begin(), d->m_pmSpecialIdVersion.end(), idVersion);
            bool isSpecialVersion = false;
            if (it != d->m_pmSpecialIdVersion.end())
            {
                isSpecialVersion = true;
            }

            if (ref.kind == "base" || ref.kind == "runtime" || ref.kind == "depend")
            {
                if (installedVersion.getMajor() == currentVersion.getMajor())
                {
                    if (installedVersion.getMinor() == currentVersion.getMinor())
                    {
                        if (installedVersion.getPatch() == currentVersion.getPatch())
                        {
                            if (d->m_pmIsForceInstall)
                            {
                                string removeStr = ref.baseInstallDir + "/" + ref.channel + "/" + ref.arch + "/" + ref.kind + "/" + ref.id + "/" + ref.module + "/" + ref.version;
                                std::cout << ref.id << " will update from version to " << pmRef.ref.version << std::endl;
                                d->m_pmOldAVersion.push_back(removeStr);
                            }
                            else
                            {
                                int maxVersion = installedVersion.compare(currentVersion);
                                if (maxVersion == 0)
                                {
                                    isInstalled = true;
                                }
                                else if (maxVersion == -1)
                                {
                                    string removeStr = ref.baseInstallDir + "/" + ref.channel + "/" + ref.arch + "/" + ref.kind + "/" + ref.id + "/" + ref.module + "/" + ref.version;
                                    std::cout << ref.id << " will update from version " << ref.version << " to " << pmRef.ref.version << std::endl;
                                    d->m_pmOldAVersion.push_back(removeStr);
                                }
                                else if (maxVersion == 1)
                                {
                                    if (pmRef.ref.isHostapp) // if ref to be installed is hostapp
                                    {
                                        string removeStr = ref.baseInstallDir + "/" + ref.channel + "/" + ref.arch + "/" + ref.kind + "/" + ref.id + "/" + ref.module + "/" + ref.version;
                                        std::cout << ref.id << " will DOWNGRADE from version " << ref.version << " to " << pmRef.ref.version << std::endl;
                                        d->m_pmOldAVersion.push_back(removeStr);
                                    }
                                    else if (isSpecialVersion == true)
                                    {
                                        if (!highVersion)
                                        {
                                            std::cout << "Warning: " << pmRef.ref.id << " Installing older version (" << pmRef.ref.version
                                                      << ") alongside existing newer version (kept for compatibility)"
                                                      << std::endl;
                                            highVersion = true;
                                        }
                                    }
                                    else
                                    {
                                        isInstalled = true;
                                    }
                                }
                            }
                            break;
                        }
                        else
                        {
                            if (installedVersion.getPatch() < currentVersion.getPatch())
                            {
                                string removeStr = ref.baseInstallDir + "/" + ref.channel + "/" + ref.arch + "/" + ref.kind + "/" + ref.id + "/" + ref.module + "/" + ref.version;
                                std::cout << ref.id << " will update from version " << ref.version << " to " << pmRef.ref.version << std::endl;
                                d->m_pmOldAVersion.push_back(removeStr);
                                continue;
                            } else if (installedVersion.getPatch() > currentVersion.getPatch())
                            {
                                if (pmRef.ref.isHostapp)
                                {
                                    string removeStr = ref.baseInstallDir + "/" + ref.channel + "/" + ref.arch + "/" + ref.kind + "/" + ref.id + "/" + ref.module + "/" + ref.version;
                                    std::cout << ref.id << " will DOWNGRADE from version " << ref.version << " to " << pmRef.ref.version << std::endl;
                                    d->m_pmOldAVersion.push_back(removeStr);
                                }
                                else if (isSpecialVersion == true)
                                {
                                    if (!highVersion)
                                    {
                                        std::cout << "Warning: " << pmRef.ref.id << " Installing older version (" << pmRef.ref.version
                                                  << ") alongside existing newer version (kept for compatibility)"
                                                  << std::endl;
                                        highVersion = true;
                                    }
                                }
                                else
                                {
                                    isInstalled = true;
                                }
                            }
                        }
                    }
                    else if (installedVersion.getMinor() < currentVersion.getMinor())
                    {
                        string removeStr = ref.baseInstallDir + "/" + ref.channel + "/" + ref.arch + "/" + ref.kind + "/" + ref.id + "/" + ref.module + "/" + ref.version;
                        std::cout << ref.id << " will update from version " << ref.version << " to " << pmRef.ref.version << std::endl;
                        d->m_pmOldAVersion.push_back(removeStr);
                        continue;
                    }
                    else
                    {
                        if (pmRef.ref.isHostapp)
                        {
                            string removeStr = ref.baseInstallDir + "/" + ref.channel + "/" + ref.arch + "/" + ref.kind + "/" + ref.id + "/" + ref.module + "/" + ref.version;
                            std::cout << ref.id << " will DOWNGRADE from version " << ref.version << " to " << pmRef.ref.version << std::endl;
                            d->m_pmOldAVersion.push_back(removeStr);
                        }
                        else if (isSpecialVersion == true)
                        {
                            if (!highVersion)
                            {
                                std::cout << "Warning: " << pmRef.ref.id << " Installing older version (" << pmRef.ref.version
                                          << ") alongside existing newer version (kept for compatibility)"
                                          << std::endl;
                                highVersion = true;
                            }
                        }
                        else
                        {
                            isInstalled = true;
                        }
                    }
                }
            }
            else
            {
                if (installedVersion < currentVersion || d->m_pmIsForceInstall || isSpecialVersion == true)
                {
                    if (installedVersion < currentVersion)
                    {
                        std::cout << ref.id << " will update from version " << ref.version << " to " << pmRef.ref.version << std::endl;
                    } else if (installedVersion > currentVersion)
                    {
                        std::cout << ref.id << " will DOWNGRADE from version " << ref.version << " to " << pmRef.ref.version << std::endl;
                    } else if (installedVersion == currentVersion)
                    {
                        std::cout << ref.id << " " << ref.version << " has been installed before !" << std::endl;
                    }

                    string removeStr = ref.baseInstallDir + "/" + ref.channel + "/" + ref.arch + "/" + ref.kind + "/" + ref.id + "/" + ref.module + "/" + ref.version;
                    d->m_pmOldAVersion.push_back(removeStr);
                }
                else
                {
                    isInstalled = true;
                    break;
                }
            }
        }
    }
    return isInstalled;
}

std::vector<std::string> KMPackageManager::extractInfoFromOK(const std::string &filepath)
{
    std::string filename = filepath.substr(filepath.find_last_of("/") + 1);
    std::vector<std::string> result;
    
    // 支持的架构列表
    std::vector<std::string> architectures = {"x86_64", "arm64", "long64", "sw64", "longarch64"};
    
    // 查找架构位置
    size_t arch_pos = std::string::npos;
    std::string found_arch;
    
    for (const auto& arch : architectures) {
        size_t pos = filename.find(arch);
        if (pos != std::string::npos) {
            arch_pos = pos;
            found_arch = arch;
            break;
        }
    }
    
    if (arch_pos == std::string::npos) {
        // 没有找到架构信息
        return result;
    }
    
    // 提取ID (架构前的部分，从开始到最后一个'-'之前)
    size_t last_dash_before_arch = filename.rfind('-', arch_pos - 1);
    std::string id;
    if (last_dash_before_arch != std::string::npos) {
        id = filename.substr(0, last_dash_before_arch);
    } else {
        id = filename.substr(0, arch_pos - 1);
    }
    
    // 架构后面的部分
    std::string remaining = filename.substr(arch_pos + found_arch.length() + 1); // +1 跳过后面的'-'
    
    // 按'-'分割剩余部分
    std::vector<std::string> parts;
    size_t start = 0;
    size_t end = remaining.find('-');
    
    while (end != std::string::npos) {
        parts.push_back(remaining.substr(start, end - start));
        start = end + 1;
        end = remaining.find('-', start);
    }
    parts.push_back(remaining.substr(start));
    
    // 根据规则提取信息
    if (parts.size() >= 4) {
        // 提取各部分信息
        std::string module = parts[parts.size() - 2];        // 倒数第一个和倒数第二个之间的为module
        std::string channel = parts[parts.size() - 3];       // 倒数第二个和倒数第三个之间的为channel
        
        // 倒数第三个之前的部分为版本信息
        std::string version;
        for (size_t i = 0; i < parts.size() - 3; i++) {
            if (!version.empty()) {
                version += "-";
            }
            version += parts[i];
        }
        
        // 按顺序存储到vector中
        result.push_back(id);
        result.push_back(found_arch);
        result.push_back(version);
        result.push_back(channel);
        result.push_back(module);
    }
    
    return result;
}

// std::vector<std::string> KMPackageManager::extractInfoFromOK(const std::string &filepath)
// {
//     std::vector<std::string> result{};

//     d->m_okFile->clearMountPoint();
//     d->m_okMetadata->layers.clear();
//     size_t pos = filepath.find(".ok");
//     string mountPoint = "/tmp/" + filepath.substr(0, pos) + "_" + std::to_string(getpid());
//     d->m_okFile->setMountPoint(mountPoint);
//     if (!d->m_okFile->loadOKFile(filepath))
//     {
//         kmlogger.info("Failed to load file: %s", filepath.c_str());
//         return result;
//     }

//     d->m_okFile->mountOK(mountPoint);
//     d->m_okMetadata = d->m_okFile->getMetadata();
//     std::vector<KMInfoJson> layers = d->m_okMetadata->layers;
//     for (auto layer : layers)
//     {   
//         result.push_back(layer.id); // id
//         for (auto arch : layer.archs)
//         {
//             result.push_back(arch); // arch
//         }
//         result.push_back(layer.version); // version
//         result.push_back(layer.channel); // channel
//         result.push_back(layer.module); // module
//     }
//     d->m_okFile->umountOK();
//     return result;
// }

int KMPackageManager::isInstalled(string name)
{
    kmlogger.debug("Check wait for installing app %s", name.c_str());

    KMPMRef pmRef = KMUtil::parseKMPMRef(name);

    if (pmRef.refSourceType == KMPACKAGE_SOURCE_TYPE_OK)
    {
        std::vector<std::string> result = extractInfoFromOK(name);
        pmRef.ref.id = result[0];
        pmRef.ref.arch = result[1];
        pmRef.ref.version = result[2];
        pmRef.ref.channel = result[3];
        pmRef.ref.module = result[4];
    }

    if (currentRefIsInstalled(pmRef))
    {
        kmlogger.info("%s is installed", name.c_str());
        return KM_ERROR_NO;
    }

    return KM_ERROR_NOT_INSTALLED;
}

int KMPackageManager::isUpgradabled(string name)
{
    kmlogger.debug("Check wait for update app %s", name.c_str());

    KMPMRef pmRef = KMUtil::parseKMPMRef(name);

    // 不安装,则不更新
    if (!currentRefIsInstalled(pmRef))
    {
        kmlogger.info("%s is not installed", name.c_str());
        return KM_ERROR_NOT_INSTALLED;
    }

    kmlogger.info("开始在远程仓库中查找 ref 对应的最新 commitid ...");

    // 下载和解析清单依赖文件 summary.json
    string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
    fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";

    int getSummaryState = getRemoteSummary(summaryUrl.string(), false);
    if (getSummaryState != KM_ERROR_NO)
    {
        kmlogger.error("Get and parse summary.json file error!");
        return getSummaryState;
    }

    // 从远程依赖文件查找对应的包是否存在，并获取所有的依赖列表
    bool isMatchedRefFlag = false;
    isMatchedRefFlag = d->m_parseSummaryJson->fuzzyMatchCompletedRef(pmRef, d->m_pmFuzzyMatchRefs);
    if (!isMatchedRefFlag)
    {
        std::cout << _("Not find this online ref ") << name << std::endl;
        return KM_ERROR_REF_NOT_FOUND;
    }

    for (const auto &ref : d->m_pmFuzzyMatchRefs)
    {
        kmlogger.debug("%s", ref.c_str());
    }

    // 依赖列表去重
    KMUtil::removeDuplicateValues(d->m_pmFuzzyMatchRefs);

    vector<string> pmMatchRefs;
    for (const auto &ref : d->m_pmFuzzyMatchRefs)
    {
        if (KMStringUtils::contains(ref, pmRef.ref.id))
        {
            pmMatchRefs.push_back(ref);
        }
    }

    // only one : "stable/x86_64/app/top.openkylin.Music/binary/2.0.1.0"
    for (const auto &ref : pmMatchRefs)
    {
        KMPMRef pmUpdateRef = KMUtil::parseSummaryFuzzyKMPMRef(ref);

        kmlogger.debug("%s", ref.c_str());

        if (!currentFuzzyRefIsInstalled(pmUpdateRef))
        {
            kmlogger.info("need update %s", ref.c_str());
            return KM_ERROR_NO;
        }
    }

    printf("%s\n", _("This app not need update!"));
    return KM_ERROR_NOT_NEED_UPDATE;
}

int KMPackageManager::getRemoteSummary(const string &summaryUrl, bool isExpired)
{
    static bool hasNetworkError = false;
    fs::path basePath = d->m_folder->getPath();
    fs::path summaryJsonPath = basePath / "summary.json";
    bool needDownload = false;
    bool needReload = false;

    kmlogger.debug("Begin to curl %s", summaryUrl.c_str());

    if (!fs::exists(summaryJsonPath))
    {
        kmlogger.info("summary.json does not exist, will download");
        fs::create_directories(basePath);
        needDownload = true;
    }
    else if (isExpired)
    {
        kmlogger.info("summary.json is expired, will update");
        needDownload = true;
    }
    else if (!d->m_util->isJsonFile(summaryJsonPath.string()))
    {
        kmlogger.error("Existing summary.json is not valid, will re-download");
        needDownload = true;
    }

    // Download if needed
    if (needDownload)
    {
        if (!KMCurl::curlApiDownload(summaryUrl, summaryJsonPath.string()))
        {
            kmlogger.error("Curl download failed. SummaryUrl: %s, Path: %s", summaryUrl.c_str(), summaryJsonPath.string().c_str());
            if (!hasNetworkError)
            {
                std::cout << _("Please check your network connection!") << std::endl;
                hasNetworkError = true;
            }
            return KM_ERROR_CURL_DOWNLOAD_FAILED;
        }

        if (!d->m_util->isJsonFile(summaryJsonPath.string()))
        {
            kmlogger.error("Downloaded summary.json is not valid");
            std::cout << _("summary.json is not valid, please check repo config URL") << std::endl;
            return KM_ERROR_SUMMARY_JSON_INVALID;
        }

        needReload = true;
    }

    // Load and parse the file
    if (d->m_parseSummaryJson->loadFile(summaryJsonPath.string(), needReload) != KM_ERROR_NO)
    {
        kmlogger.error("Failed to load summary.json");
        return KM_ERROR_LOAD_FILE_FAILED;
    }

    return KM_ERROR_NO;
}

int KMPackageManager::getAllFuzzyMatchRefVector(const vector<string> &vectorIds, PackageManagerOptions pmOptions, TaskType taskType)
{
    for (const auto &name : vectorIds)
    {
        kmlogger.debug("Install app %s", name.c_str());
        bool isMatchedRefFlag = false;

        KMPMRef pmRef = d->m_util->parseKMPMRef(name);
        d->m_util->printKMPMRef(name, pmRef);

        // 如果用户指定了 arch，则覆盖默认的 arch
        if (!pmOptions.arch.empty())
        {
            pmRef.ref.arch = pmOptions.arch;
        }

        if (!pmOptions.kind.empty())
        {
            pmRef.ref.kind = pmOptions.kind;
        }

        if (!pmRef.ref.version.empty() && pmOptions.compatible == false)
        {
            pmRef.ref.isSpecialVersion = true;

            if (!d->m_isOffInstall)
            {
                d->m_pmSpecialIdVersion.push_back(pmRef.ref.id + pmRef.ref.version);
            }
        }

        pmRef.ref.isForceInstall = pmOptions.force;
        d->m_pmInstallId.push_back(pmRef.ref.id);

        switch (taskType)
        {
        case TaskType::TASK_TYPE_INSTALL:
            // 已安装当前软件包或指定版本包则不再安装
            if (currentRefVersionIsInstalled(pmRef))
            {
                if (!pmOptions.force)
                {
                    std::cout << _("This package has been installed! ") << pmRef.ref.id << std::endl;
                    return KM_ERROR_NOT_UNINSTALLED;
                }
                kmlogger.info("当前软件包 %s 已安装", name.c_str());
                continue;
            }

            break;
        case TaskType::TASK_TYPE_UPDATE:
            // 未安装该包或该包指定版本,则不更新，直接返回
            if (!currentRefIsUninstalled(pmRef))
            {
                if (pmRef.ref.version.empty())
                {
                    kmlogger.info("未安装该软件包 %s", name.c_str());
                    std::cout << _("Not install this ref ") << name << std::endl;
                    return KM_ERROR_REF_NOT_INSTALLED;
                }
            }
            break;
        case TaskType::TASK_TYPE_UNINSTALL:
            // 未安装该包或该包指定版本,则不更新，直接返回
            if (!currentRefIsUninstalled(pmRef))
            {
                kmlogger.error("%s not installed!", name.c_str());
                printf("%s not installed!", name.c_str());
                return KM_ERROR_REF_NOT_INSTALLED;
            }
            break;
        case TaskType::TASK_TYPE_REPAIR:
            // 未安装该包或该包指定版本,则不修复，直接返回
            if (!currentRefIsUninstalled(pmRef))
            {
                kmlogger.error("%s not installed!", name.c_str());
                printf("%s not installed!", name.c_str());
                return KM_ERROR_REF_NOT_INSTALLED;
            }
            break;
        default:
            break;
        }

        vector<string> fuzzyMatchRefs;
        // 从远程依赖文件查找对应的包是否存在，并获取所有的依赖列表
        isMatchedRefFlag = d->m_parseSummaryJson->fuzzyMatchCompletedRef(pmRef, fuzzyMatchRefs);
        string notInstallable = d->m_parseSummaryJson->getNotInstallable();
        vector<std::string> notFind = d->m_parseSummaryJson->getNotFind();

        bool installed = d->m_isOffInstall ? d->m_parseSummaryJson->currentFuzzyRefIsInstalled(pmRef) : currentRefIsInstalled(pmRef);

        if (!notInstallable.empty())
        {
            if (!installed)
            {
                d->m_pmCanNotInstallVector.push_back(name);

                if (pmRef.ref.id == notInstallable)
                {
                    std::cout << _("Can not install this package ") << name << std::endl;
                }
                else
                {
                    std::cout << name << _(" Can not install the dependencies of this package:") << notInstallable << std::endl;
                }
            }
            else
            {
                std::cout << _("This package has been installed! ") << pmRef.ref.id << std::endl;
            }

            d->m_parseSummaryJson->clearNotInstallable();
            continue;
        }
        if (!notFind.empty())
        {
            if (!installed)
            {
                d->m_pmCanNotInstallVector.push_back(name);

                if (notFind[0] == pmRef.ref.id)
                {
                    std::cout << _("Not find this online package ") << name << std::endl;
                }
                else
                {
                    std::cout << name << _(" Can not find the dependencies of this package:") << std::endl;
                    for (auto it : notFind)
                    {
                        if (it == pmRef.ref.id)
                        {
                            continue;
                        }

                        std::cout << it << std::endl;
                    }
                }
            }
            else
            {
                std::cout << _("This package has been installed! ") << pmRef.ref.id << std::endl;
            }

            d->m_parseSummaryJson->clearNotInstallable();
            continue;
        }

        d->m_pmFuzzyMatchRefs.insert(d->m_pmFuzzyMatchRefs.end(), fuzzyMatchRefs.begin(), fuzzyMatchRefs.end());

        for (const auto &ref : d->m_pmFuzzyMatchRefs)
        {
            kmlogger.debug("%s", ref.c_str());
        }
    }

    // 依赖列表去重
    KMUtil::removeDuplicateValues(d->m_pmFuzzyMatchRefs);
    return KM_ERROR_NO;
}

int KMPackageManager::getCompletedRef(std::string name, std::string version, std::string branch, std::vector<std::string> &completeRef)
{
    std::string module = "binary";
    if (branch.empty())
    {
        branch = "stable";
    }
    std::string ref = name + "/" + version + "/" + module + "/" + branch;
    KMPMRef pmRef = d->m_util->parseKMPMRef(ref);
    // 下载和解析清单依赖文件 summary.json
    string ostreeRepoUrl = d->m_ostreeHandler->getRemoteUrl(REPO_NAME);
    fs::path summaryUrl = fs::path(ostreeRepoUrl) / "summary.json";

    int getSummaryState = getRemoteSummary(summaryUrl.string(), false);
    if (getSummaryState != KM_ERROR_NO)
    {
        kmlogger.error("Get and parse summary.json file error!");
        return getSummaryState;
    }
    // 构建完整的 ostree ref
    pmRef.ref.isSpecialVersion = true;
    bool isMatchedRefFlag = d->m_parseSummaryJson->fuzzyMatchCompletedRef(pmRef, completeRef);
    if (!isMatchedRefFlag)
    {
        return KM_ERROR_GET_REF_INFO_FAILED; 
    }
    return KM_ERROR_NO;
}

int KMPackageManager::getRemoteStatusInfo(const std::string name, const std::string version, const std::string branch, std::string &packInfoToJson, int &errorCode)
{
    errorCode = KM_ERROR_NO;
    packInfoToJson = KMDbusJson::packRemoteStatusToJson("", "", "");
    
    if (name.empty() || version.empty()) 
    {
        kmlogger.info("Name or version is empty, they are provided for remote status check.");
        return KM_ERROR_INVALID_ARGS;
    }

    /* TODO: 获取软件包的签名状态*/
    bool signStatus = true;
    std::string signCN = "麒麟软件有限公司";

    std::vector<std::string> completeRef;
    errorCode = getCompletedRef(name, version, branch, completeRef);
    
    std::string updateTime;
    if (errorCode == KM_ERROR_NO && !completeRef.empty()) 
    {
        std::string ref = completeRef.front();
        if (!ref.empty()) 
        {
            //updateTime = d->m_ostreeHandler->getBranchTimestamp(ref);
            updateTime = d->m_ostreeHandler->getBranchTimestamp(ref.c_str());
        }
    }

    packInfoToJson = KMDbusJson::packRemoteStatusToJson(updateTime, signStatus, signCN);
    kmlogger.debug("Remote status info for package %s is: %s", name.c_str(), packInfoToJson.c_str());

    return errorCode;
}

void KMPackageManager::getUsefulRefList()
{
    string preRef;
    for (auto it = d->m_pmFuzzyMatchRefs.begin(); it != d->m_pmFuzzyMatchRefs.end(); it++)
    {
        string ref = *it;
        if (preRef.empty())
        {
            preRef = ref;
            continue;
        }
        else
        {
            KMPMRef pmFuzzyRef = KMUtil::parseSummaryFuzzyKMPMRef(ref);
            KMPMRef pmPreRef = KMUtil::parseSummaryFuzzyKMPMRef(preRef);
            if (pmFuzzyRef.ref.id == pmPreRef.ref.id && pmFuzzyRef.ref.kind == pmPreRef.ref.kind && pmFuzzyRef.ref.module == pmPreRef.ref.module && pmFuzzyRef.ref.arch == pmPreRef.ref.arch && pmFuzzyRef.ref.channel == pmPreRef.ref.channel)
            {
                if (pmFuzzyRef.ref.kind == "app")
                {
                    if (KMVersion::parse(pmFuzzyRef.ref.version) > KMVersion::parse(pmPreRef.ref.version))
                    {
                        auto findFuzzyIt = std::find(d->m_pmFuzzyMatchRefs.begin(), d->m_pmFuzzyMatchRefs.end(), preRef);
                        if (findFuzzyIt != d->m_pmFuzzyMatchRefs.end())
                        {
                            it = d->m_pmFuzzyMatchRefs.erase(findFuzzyIt);
                        }
                        preRef = ref;
                        continue;
                    }
                }
                else
                {
                    std::istringstream currentVersion(pmFuzzyRef.ref.version);
                    std::istringstream preVersion(pmPreRef.ref.version);
                    int major, minor, patch, secure;
                    int preMajor, preMinor, prePatch, preSecure;
                    char dot;
                    currentVersion >> major >> dot >> minor >> dot >> patch;
                    preVersion >> preMajor >> dot >> preMinor >> dot >> prePatch;
                    if (major != preMajor || minor != preMinor)
                    {
                        preRef = ref;
                        continue;
                    }
                    else
                    {
                        if (patch >= prePatch)
                        {
                            auto findFuzzyIt = std::find(d->m_pmFuzzyMatchRefs.begin(), d->m_pmFuzzyMatchRefs.end(), preRef);
                            if (findFuzzyIt != d->m_pmFuzzyMatchRefs.end())
                            {
                                std::string idVersion = pmPreRef.ref.id + pmPreRef.ref.version;
                                auto idVersionIt = std::find(d->m_pmSpecialIdVersion.begin(), d->m_pmSpecialIdVersion.end(), idVersion);
                                if (idVersionIt == d->m_pmSpecialIdVersion.end())
                                {
                                    it = d->m_pmFuzzyMatchRefs.erase(findFuzzyIt);
                                }
                            }
                            preRef = ref;
                            continue;
                        }
                    }
                }
            }
            else
            {
                preRef = ref;
            }
        }
    }
    return;
}

void KMPackageManager::getDownloadRefList(TaskType taskType)
{
    d->m_pmRefDownloadList.clear();
    g_refDownloadListForProgress.clear();

    for (auto &ref : d->m_pmFuzzyMatchRefs)
    {
        KMPMRef pmFuzzyRef = KMUtil::parseSummaryFuzzyKMPMRef(ref);
        switch (taskType)
        {
        case TaskType::TASK_TYPE_INSTALL:
            // 安装时，过滤掉已安装的软件
            if (currentFuzzyRefIsInstalled(pmFuzzyRef))
            {
                std::string idVersion = pmFuzzyRef.ref.id + pmFuzzyRef.ref.version;
                auto it = std::find(d->m_pmSpecialIdVersion.begin(), d->m_pmSpecialIdVersion.end(), idVersion);
                if (it == d->m_pmSpecialIdVersion.end())
                {
                    auto idIt = std::find(d->m_pmInstallId.begin(), d->m_pmInstallId.end(), pmFuzzyRef.ref.id);

                    if (idIt != d->m_pmInstallId.end())
                    {
                        std::cout << _("This package has been installed! ") << pmFuzzyRef.ref.id << std::endl;
                    }

                    continue;
                }
            }
            break;
        case TaskType::TASK_TYPE_UPDATE:
            // 更新时也是过滤掉已安装的软件
            if (currentFuzzyRefIsInstalled(pmFuzzyRef))
            {
                continue;
            }
            break;
        case TaskType::TASK_TYPE_REPAIR:
            // 修复时不过滤掉已安装的软件
            if (!currentFuzzyRefIsInstalled(pmFuzzyRef))
            {
                KMPMRef pmRef = pmFuzzyRef;
                pmRef.ref.version = "";
                if (!currentRefIsInstalled(pmRef))
                {
                    continue;
                }
            }
            break;
        default:
            break;
        }

        kmlogger.debug("Installing ref : %s", ref.c_str());

        // 再次构建完整的 ostree ref
        pmFuzzyRef.completedRef = KMUtil::dupKMPMCompletedRef(pmFuzzyRef);
        // d->m_pmDownloadRefs.clear();
        d->m_pmDownloadRefs.push_back(pmFuzzyRef.completedRef);
        d->m_parseSummaryJson->getSummaryInfo(pmFuzzyRef);

        d->m_pmRefDownloadList.push_back(pmFuzzyRef);
        g_refDownloadListForProgress.push_back(pmFuzzyRef);
    }
}

bool KMPackageManager::printUninstallDependsOnList(const vector<std::string> &UninstallVector)
{
    if (UninstallVector.empty())
    {
        return false;
    }

    // 初始化最大宽度
    size_t maxIdWidth = 0;
    size_t maxModuleWidth = 0;
    size_t maxVersionWidth = 0;
    size_t maxChannelWidth = 0;

    // 第一次遍历：计算最大宽度
    for (auto &uninstallIt : UninstallVector)
    {
        std::stringstream ss(uninstallIt);
        std::string token;
        vector<std::string> tokens;

        while (std::getline(ss, token, '/'))
        {
            tokens.push_back(token);
        }

        int tokensSize = tokens.size();
        if (tokensSize >= 6) {
            maxIdWidth = std::max(maxIdWidth, tokens[tokensSize - 3].length());
            maxModuleWidth = std::max(maxModuleWidth, tokens[tokensSize - 2].length());
            maxVersionWidth = std::max(maxVersionWidth, tokens[tokensSize - 1].length());
            maxChannelWidth = std::max(maxChannelWidth, tokens[tokensSize - 6].length());
        }
    }

    // 设置最小宽度（确保不小于列标题）
    const size_t minIdWidth = 2;         // "ID" 标题长度
    const size_t minModuleWidth = 6;     // "Module" 标题长度
    const size_t minVersionWidth = 7;    // "Version" 标题长度
    const size_t minChannelWidth = 7;    // "Channel" 标题长度

    maxIdWidth = std::max(maxIdWidth, minIdWidth) + 5;
    maxModuleWidth = std::max(maxModuleWidth, minModuleWidth) + 5;
    maxVersionWidth = std::max(maxVersionWidth, minVersionWidth) + 5;
    maxChannelWidth = std::max(maxChannelWidth, minChannelWidth) + 5;


    d->m_formatter->setColumnWidth(maxIdWidth, maxModuleWidth, maxVersionWidth, maxChannelWidth, 25, 25, 30, 25, 35, 35);
    d->m_formatter->setShowArch(false);
    d->m_formatter->setShowSize(false);
    d->m_formatter->setShowName(false);
    d->m_formatter->setShowDescription(false);
    d->m_formatter->setShowChannel(true);
    d->m_formatter->printHeader();

    bool foundAnyEntries = false;
    bool printHeader = false;
    
    // 第二次遍历：打印数据
    for (auto &uninstallIt : UninstallVector)
    {
        std::stringstream ss(uninstallIt);
        std::string token;
        vector<std::string> tokens;

        while (std::getline(ss, token, '/'))
        {
            tokens.push_back(token); // 将切分后的部分添加到 tokens 向量中
        }

        int tokensSize = tokens.size();
        KMEntry entry;
        entry.id = tokens[tokensSize - 3];
        entry.module = tokens[tokensSize - 2];
        entry.version = tokens[tokensSize - 1];
        entry.channel = tokens[tokensSize - 6];
        d->m_formatter->printEntry(entry);
    }

    if (!foundAnyEntries)
    {
        // std::cout << "No matching packages found for uninstallation.\n";
        return false;
    }

    d->m_formatter->printFooter();

    return foundAnyEntries;
}

void KMPackageManager::printDownloadRefList(const vector<KMPMRef> &downloadRefs)
{
    // 初始化最大宽度
    size_t maxIdWidth = 0;
    size_t maxNameWidth = 0;
    size_t maxVersionWidth = 0;

    // 第一次遍历：计算最大宽度
    for (const auto &pmRef : downloadRefs) 
    {
        maxIdWidth = std::max(maxIdWidth, pmRef.ref.id.length());
        maxNameWidth = std::max(maxNameWidth, pmRef.name.length());
        maxVersionWidth = std::max(maxVersionWidth, pmRef.ref.version.length());
    }

    // 设置最小宽度（确保不小于列标题）
    const size_t minIdWidth = 10;      // "ID" 标题长度
    const size_t minNameWidth = 20;    // "Name" 标题长度
    const size_t minVersionWidth = 15; // "Version" 标题长度

    maxIdWidth = std::max(maxIdWidth, minIdWidth) + 5;
    maxNameWidth = std::max(maxNameWidth, minNameWidth) + 5;
    maxVersionWidth = std::max(maxVersionWidth, minVersionWidth) + 5;

    // 设置列宽（id, name, version 使用动态宽度，其他列保持固定宽度）
    d->m_formatter->setColumnWidth(maxIdWidth, maxNameWidth, maxVersionWidth, 10, 25, 25, 30, 25, 35, 35);
    d->m_formatter->setShowArch(false);
    d->m_formatter->setShowChannel(true);
    d->m_formatter->printHeader();

    // 第二次遍历：实际打印
    for (const auto &pmRef : downloadRefs)
    {
        string installedSize = KMUtil::formatInstalledSize((double)pmRef.installedSize);

        KMEntry entry;
        entry.id = pmRef.ref.id;
        entry.name = pmRef.name;
        entry.description = pmRef.description;
        entry.module = pmRef.ref.module;
        entry.version = pmRef.ref.version;
        entry.arch = pmRef.ref.arch;
        entry.channel = pmRef.ref.channel;
        entry.size = installedSize;

        d->m_formatter->printEntry(entry);
    }

    d->m_formatter->printFooter();
}

bool KMPackageManager::printAssumeYesChoice(PackageManagerOptions pmOptions)
{
    if (!pmOptions.assumeYes)
    {
        std::cout << _("Do you want to install these changes? [Y/n]: ");

        char yesOption;

        while (true)
        {
            yesOption = std::cin.get();

            // 检查是否遇到 EOF(Ctrl+D)
            if (std::cin.eof())
            {
                std::cout << _("\nInput ended unexpectedly. Cancel install.\n");
                return false;
            }

            if (d->m_util->isYes(yesOption))
            {
                break;
            }
            else if (d->m_util->isNo(yesOption))
            {
                std::cout << _("Cancel install.\n");
                return false;
            }
            else
            {
                std::cout << _("Do you want to install these changes? [Y/n]: ");
            }
        }
    }

    return true;
}

int KMPackageManager::getTerminalWidth()
{
    struct winsize w{};
    if (!isatty(STDOUT_FILENO) || ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) == -1 || w.ws_col == 0)
    {
        kmlogger.info("Failed to get terminal width, defaulting to 80.");
        return 80;
    }
    ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
    return w.ws_col;
}

static gint64 networkDisconnectedTime = 0;
static bool isNetworkDisconnected = false;
static bool isPrintDisconnected = false;
static bool isPrintFailed = false;

void KMPackageManager::checkAndHandleNetwork(std::shared_ptr<KMOSTreeHandler> handler)
{
    int networkStatus = checkNetworkConnection(handler);

    if (networkStatus == -1) 
    {
        // ping 不存在，跳过网络检查（默认网络正常）
        kmlogger.info("无法检测网络(ping 不存在)，继续执行");
        return;  // 直接返回，不处理网络断开逻辑
    }
    else if (networkStatus == 0) 
    {
        // 网络断开
        if (!isNetworkDisconnected) 
        {
            // 第一次检测到网络断开
            networkDisconnectedTime = g_get_monotonic_time();
            isNetworkDisconnected = true;
            clearOldProgress();
            std::cout << _("Network disconnected, trying to reconnect...") << std::endl;
        }
        else 
        {
            guint64 disconnectedDuration = (g_get_monotonic_time() - networkDisconnectedTime) / G_USEC_PER_SEC;
            if (disconnectedDuration > 10) 
            {
                std::cout << "\n" << std::endl;
                KMError(_("Network connection failed. Check network settings or retry."));
                exit(1);
            }
        }
    }
    else if (isNetworkDisconnected) 
    {
        // 网络恢复
        isNetworkDisconnected = false;
        clearOldProgress();
        std::cout << _("Network connection restored, resuming installation...") << std::endl;
    }
}

// 安全 strlen，避免 NULL 且限制最大长度
static inline size_t safe_strnlen(const char *s, size_t maxlen) 
{
    if (!s) return 0;
    const char *p = s;
    size_t count = 0;
    while (*p && count < maxlen) 
    {
        p++;
        count++;
    }
    return count;
}

/**
 * @brief 进度处理回调函数
 *
 * 进度条处理分成3个步骤：
 *  - 1. 当拉取 metadata 时， 增长到 5%;
 *  - 2. 下载数据一直到 97%;
 *  - 3. 写入 ostree objects 为最后的 3%
 *
 * @param progressStatus 在 ostree pull 时，发送的进度等信息结构体
 */
void KMPackageManager::progressCallback(ProgressStatus progressStatus)
{
    // std::lock_guard<std::mutex> lock(progressMutex);

    kmlogger.debug("enter installProgressCallback, current ref: %s", progressStatus.ref.c_str());
    char buf[1024 * 8] = {0};
    guint64 total = 0;
    guint64 elapsedTime;
    guint newProgress = 0;
    gboolean estimating = false;
    guint64 totalTransferred;
    gboolean lastWasMetadata = progressStatus.lastWasMetadata;
    gchar *formattedBytesTotalTransferred = NULL;
    gchar *formattedBytesTotal = NULL;
    gchar *formattedBytesSec = NULL;
    gchar *speed = NULL;

    int i;
    int fullSize, partial;
    int barLength;
    const char *partialBlocks[] = {" ", "▏", "▎", "▍", "▌", "▋", "▊", "▉"};
    const char *fullBlock = "█";

    int rows = 24, cols = 80;

    elapsedTime = (g_get_monotonic_time() - progressStatus.startTime) / G_USEC_PER_SEC;
    kmlogger.debug("elapsedTime: %ld", elapsedTime);

    if (*progressStatus.ostreeStatus)
    {
        // 当ostree_status 有反馈，则代表fetch成功，总进度到了100%
        kmlogger.debug("install ostree status receive pull success");
        newProgress = 100;
        progressStatus.progress = 100;
    }
    else
    {
        totalTransferred = progressStatus.bytesTransferred + progressStatus.transferredExtraDataBytes;
        formattedBytesTotalTransferred = g_format_size_full(totalTransferred, G_FORMAT_SIZE_IEC_UNITS);

        progressStatus.lastWasMetadata = false;

        if (progressStatus.totalDeltaParts == 0 && (progressStatus.outstandingMetadataFetches > 0 || lastWasMetadata) && progressStatus.metadataFetched < 20)
        {
            /* 在没有完成 metadata 处理时，我们需要执行2次回调函数，
-            * 因为有时会遇到仅处理元数据会触发调用，但却没进行处理和添加更多元数据。*/
            if (progressStatus.outstandingMetadataFetches > 0)
            {
                progressStatus.lastWasMetadata = true;
            }

            /* At this point we don't really know how much data there is, so we have to make a
-            * guess. Since its really hard to figure out early how much data there is we report 1%
-            * until all objects are scanned. */
            estimating = true;
            snprintf(buf, sizeof(buf), _("Downloading metadata: %u/(estimating) %s"), progressStatus.fetched, formattedBytesTotalTransferred ? formattedBytesTotalTransferred : "");
            kmlogger.debug("Downloading metadata buf: %s", buf);

            /* 增长到 5% 直到所有元数据都被拉取了 */
            newProgress = 0;
            if (progressStatus.requested > 0)
            {
                newProgress = progressStatus.fetched * 5 / progressStatus.requested;
            }
        }
        else
        {
            if (progressStatus.totalDeltaParts > 0)
            {
                /* 仅仅使用 deltas, 因此我们可以忽略 regular objects 来获得更好的 sizes;
-                 *
-                 * fetchedDeltaPartSize 所有 delta 部分 和 fallback objects 参数的总大小，
-                 * 它是在最开始可以获得的，因此不用下载。
-                 */
                total = progressStatus.totalDeltaPartSize - progressStatus.fetchedDeltaPartSize + progressStatus.totalExtraDataBytes;
                formattedBytesTotal = g_format_size_full(total, G_FORMAT_SIZE_IEC_UNITS);

                snprintf(buf, sizeof(buf), _("Downloading: %s/%s"), formattedBytesTotalTransferred ? formattedBytesTotalTransferred : "", formattedBytesTotal ? formattedBytesTotal : "");
                kmlogger.debug("Downloading buf: %s", buf);
            }
            else
            {
                /* Non-deltas, 因此我们不能知道除了 object 计数和额外数据的字节大小以外的任何东西，
-                      为了比较它们和额外数据，我们使用平均对象大小来评估总大小。*/
                double averageObjectSize = 1;
                if (progressStatus.fetched > 0)
                {
                    averageObjectSize = progressStatus.bytesTransferred / (double)progressStatus.fetched;
                }
                total = averageObjectSize * progressStatus.requested + progressStatus.totalExtraDataBytes;
                formattedBytesTotal = g_format_size_full(total, G_FORMAT_SIZE_IEC_UNITS);

                snprintf(buf, sizeof(buf), _("Downloading extra data: %s/%s"), formattedBytesTotalTransferred ? formattedBytesTotalTransferred : "", formattedBytesTotal ? formattedBytesTotal : "");
                kmlogger.debug("下载额外数据 buf: %s", buf);

                snprintf(buf, sizeof(buf), _("Downloading files: %d/%d %s"), progressStatus.fetched, progressStatus.requested, formattedBytesTotalTransferred ? formattedBytesTotalTransferred : "");
                kmlogger.debug("下载文件: %s", buf);
            }

            if (total > 0)
            {
                newProgress = 5 + ((totalTransferred / (gdouble)total) * 92); // 这个数据会因下载额外数据导致不准，比如会从 75 降到 48
            }
            // else
            // {
            //     newProgress = 97;
            // }

            /* 增加最后写入对象的 3% 进度 */
            newProgress += getWriteProgress(progressStatus.outstandingWrites);
        }

        if (elapsedTime > 0)
        {
            formattedBytesSec = g_format_size(totalTransferred / elapsedTime);
            snprintf(buf, sizeof(buf), " (%s/s)", formattedBytesSec ? formattedBytesSec : "");
            kmlogger.debug("totalTransferred: %ld elapsedTime: %ld buf: %s", totalTransferred, elapsedTime, buf);
        }
    }

    kmlogger.info("newProgress: %d currentPercent: %d", newProgress, currentPercent);
    if (newProgress < currentPercent)
    {
        newProgress = currentPercent;
    }
    else
    {
        if (newProgress == 100)
        {
            currentPercent = 0;
        }
        else
        {
            currentPercent = newProgress;
        }
    }

    progressStatus.lastTotal = total;
    kmlogger.debug("newProgress: %d\n", newProgress);
    if (newProgress > 100)
    {
        if (!progressStatus.reportedOverflow)
        {
            kmlogger.error("Unexpectedly got > 100%% progress, limiting");
        }
        progressStatus.reportedOverflow = true;
        newProgress = 100;
    }

    guint singlePercent = newProgress; // 单一软件包下载进度，这个单一进度会因下载额外数据导致不准，比如会从 75 降到 48

    std::string currentRefId = progressStatus.ref; // 赋值为当前 ref

    uint64_t totalSize = getTotalSize();
    uint64_t singleSize = getSingleSize(progressStatus.ref, currentRefId);

    guint totalPercent = 0; // 总进度
    uint64_t currentProgress = 0; // 当前的进度
    std::string lastDownloadRef = g_refDownloadListForProgress.back().completedRef;
    kmlogger.debug("lastDownloadRef: %s", lastDownloadRef.c_str());

    for (const auto &item : g_refDownloadListForProgress)
    {
        kmlogger.debug("completedRef: %s size:%ld ", item.completedRef.c_str(), item.installedSize);
        if (item.completedRef == progressStatus.ref)
        {
            currentProgress += (double)singlePercent / 100 * singleSize;
            break;
        }
        currentProgress += item.installedSize;
    }

    totalPercent = (double)currentProgress * 100 / totalSize;

    kmlogger.info("singlePercent:%d singleSize: %ld currentProgress: %ld  totalSize: %ld totalPercent: %d", singlePercent, singleSize, currentProgress, totalSize, totalPercent);

    progressStatus.progress = totalPercent;
    progressStatus.estimating = estimating;

    // if (elapsedTime > 0)
    // {
    //     std::string remaining;
    //     if (elapsedTime > 3 && singlePercent > 0)
    //     {
    //         guint64 totalTime = elapsedTime * 100 / (double)singlePercent;
    //         remaining = formatDuration(totalTime - elapsedTime);
    //         kmlogger.debug("totalTime:%ld elapsedTime:%ld  remaining_time:%ld remaining: %s", totalTime, elapsedTime, totalTime - elapsedTime, remaining.c_str());
    //     }

    //     guint64 remainingBytes = totalSize - currentProgress;
    //     std::string remainingStr = calculateDownloadTime(string(formattedBytesSec), remainingBytes);
    //     preRemaining = (remainingStr != "") ? remainingStr : preRemaining;
    //     kmlogger.debug("remainingBytes: %ld remainingStr: %s preRemaining:%s", remainingBytes, remainingStr.c_str(), preRemaining.c_str());
    // }

    int terminalWidth = getTerminalWidth();
    barLength = std::max(10, terminalWidth - 25); // 修正：下限保护
    fullSize = (barLength * totalPercent) / 100;
    partial = (((barLength * totalPercent) % 100) * G_N_ELEMENTS(partialBlocks)) / 100;

    if (terminalWidth != lastWidth)
    {
        lastWidth = terminalWidth;
    }

    char str[1024 * 8] = {0};

    // 构建静态信息部分
    std::string currentStaticInfo = "正在下载 " + currentRefId;

    if (currentStaticInfo != lastStaticInfo || !staticInfoDisplayed)
    {
        clearOldProgress();
        std::cout << currentStaticInfo << "\n";
        lastStaticInfo = currentStaticInfo;
        staticInfoDisplayed = true;
    }
    snprintf(str, sizeof(str), "[");

    // 进度条拼接，防止溢出
    size_t pos = safe_strnlen(str, sizeof(str) - 1);
    for (i = 0; i < barLength && pos < (int)sizeof(str) - 2; i++)
    {
        str[pos++] = (i < fullSize) ? '#' : '.';
    }
    str[pos] = '\0';

    size_t curLen = safe_strnlen(str, sizeof(str) - 1);
    snprintf(str + curLen, sizeof(str) - curLen, "] %3d%%", totalPercent);

    // 速度显示
    if (elapsedTime > 0 && totalPercent < 100)
    {
        if (!formattedBytesSec)
            formattedBytesSec = g_format_size(totalTransferred / elapsedTime);
        if (formattedBytesSec)
        {
            speed = g_strdup_printf("%s/s", formattedBytesSec);
            size_t curLen = safe_strnlen(str, sizeof(str) - 1);
            snprintf(str + curLen, sizeof(str) - curLen, " %s", speed);
        }
    }
    else
    {
        speed = g_strdup_printf("5 MB/s");
        size_t curLen = safe_strnlen(str, sizeof(str) - 1);
        snprintf(str + curLen, sizeof(str) - curLen, " %s", speed);
    }

    clearOldProgress();
    std::cout << str << std::flush;

    lastOutput = std::string(str);
    lastProgressStr = lastOutput;

    kmlogger.debug("currentRef: %s lastRef: %s progress", progressStatus.ref.c_str(), progressStatus.lastRef.c_str());
    KMOSTreeHandler::replaceRef(progressStatus.lastRef);
    if (progressStatus.ref == progressStatus.lastRef && *progressStatus.ostreeStatus)
    {
        totalPercent = 100;
        printf("\n");
    }

    globalProgressStatus.speed = speed ? std::string(speed) : "5 MB/s";
    globalProgressStatus.refId = currentRefId;
    globalProgressStatus.progress = totalPercent;
    globalProgressStatus.timeout = 5;

    kmlogger.debug("install progress------>>:  refId:%s progress:%d speed:%s timeout:%d", globalProgressStatus.refId.c_str(), globalProgressStatus.progress, globalProgressStatus.speed.c_str(), globalProgressStatus.timeout);

    progressJson = KMDbusJson::packProgressInfoToJson(globalProgressStatus.refId, globalProgressStatus.progress, globalProgressStatus.speed, globalProgressStatus.timeout);

    updateProgress();

    // 内存释放
    if (formattedBytesTotalTransferred)
        g_free(formattedBytesTotalTransferred);
    if (formattedBytesTotal)
        g_free(formattedBytesTotal);
    if (formattedBytesSec)
        g_free(formattedBytesSec);
    if (speed)
        g_free(speed);

    fflush(stdout);
}

/**
 * 检查网络连接状态
 * @return true 网络正常，false 网络断开
 */
int KMPackageManager::checkNetworkConnection(std::shared_ptr<KMOSTreeHandler> handler)
{
    std::string ostreeRepoUrl = handler->getRemoteUrl(REPO_NAME);
    
    // 去掉协议头
    size_t pos = ostreeRepoUrl.find("://");
    std::string hostPart = (pos != std::string::npos) ? ostreeRepoUrl.substr(pos + 3) : ostreeRepoUrl;

    // 截掉路径，只保留 host[:port]
    pos = hostPart.find('/');
    if (pos != std::string::npos)
        hostPart = hostPart.substr(0, pos);

    // 如果是 IPv6 格式 [addr]:port
    if (hostPart[0] == '[') 
    {
        size_t bracketEnd = hostPart.find(']');
        if (bracketEnd != std::string::npos)
            hostPart = hostPart.substr(0, bracketEnd + 1); // 保留 [addr]
    } 
    else 
    {
        // IPv4 或域名，去掉 :port
        size_t colonPos = hostPart.find(':');
        if (colonPos != std::string::npos)
            hostPart = hostPart.substr(0, colonPos);
    }

    // 先检查 ping 命令是否存在
    int pingCheck = system("command -v ping >/dev/null 2>&1");
    if (pingCheck != 0) 
    {
        kmlogger.info("ping 命令不存在，跳过网络检查");
        return -1;  // -1 表示 ping 不可用，跳过检查
    }

    // 构造 ping 命令
    std::string pingCmd = "ping -c 1 " + hostPart + " > /dev/null 2>&1";

    // 执行
    int ret = system(pingCmd.c_str());
    kmlogger.info("Ping %s: %s", hostPart.c_str(), ret == 0 ? "success" : "failed");
    return (ret == 0) ? 1 : 0;  // 1=成功，0=失败
}

void KMPackageManager::clearOldProgress()
{
    if (!lastProgressStr.empty() && lastWidth > 0)
    {
        int lines = (lastProgressStr.length() + lastWidth - 1) / lastWidth;
        std::cout << "\r";
        for (int i = 0; i < lines; ++i)
        {
            std::cout << "\033[K";
            if (i < lines - 1)
            {
                std::cout << "\033[A";
            }
        }
        std::cout << std::flush;
    }
}

int KMPackageManager::getWriteProgress(int outstandingWrites)
{
    return outstandingWrites > 0 ? (int)(3 / (double)outstandingWrites) : 3;
}

uint64_t KMPackageManager::getTotalSize()
{
    uint64_t sumSize = 0;
    for (const auto &ref : g_refDownloadListForProgress)
    {
        kmlogger.debug("completedRef: %s installedSize:%ld", ref.completedRef.c_str(), ref.installedSize);

        sumSize += ref.installedSize;
    }

    return sumSize;
}

uint64_t KMPackageManager::getSingleSize(const string &completedRef, string &id)
{
    uint64_t singleSize = 0; // 需初始化
    id.clear();

    for (const auto &pmRef : g_refDownloadListForProgress)
    {
        kmlogger.debug("completedRef: %s installedSize:%ld", pmRef.completedRef.c_str(), pmRef.installedSize);
        std::string pmCompleteRef = pmRef.completedRef;
        KMOSTreeHandler::replaceRef(pmCompleteRef);
        if (completedRef == pmCompleteRef)
        {
            singleSize = pmRef.installedSize;
            id = pmRef.ref.id;
            break;
        }
    }

    if (singleSize == 0)
    {
        kmlogger.warn("No matching package found for completedRef: %s", completedRef.c_str());
    }

    return singleSize;
}

void KMPackageManager::updateProgress()
{
    // 只有当 globalProgressCallback
    // 是有效的时候才调用,即已经与某个可调用对象关联，并且没有被释放，避免 bad_function_call
    if (globalProgressCallback && progressJson != "")
    {
        globalProgressCallback(progressJson);
    }
}

string KMPackageManager::formatDuration(guint64 duration)
{
    int h, m, s;

    std::stringstream ss;

    m = duration / 60;
    s = duration % 60;
    h = m / 60;
    m = m % 60;

    if (h > 0)
    {
        // 使用流操作符进行格式化，输出为两位数
        ss.fill('0'); // 填充字符为 '0'
        ss.width(2);  // 设置宽度为 2
        ss << h << ":";
    }

    ss.fill('0');
    ss.width(2);
    ss << m << ":";

    ss.fill('0');
    ss.width(2);
    ss << s;

    return ss.str();
}

std::string KMPackageManager::calculateDownloadTime(const std::string &speed, guint64 sizeBytes)
{
    long int downloadSpeed;
    std::string result;

    kmlogger.debug("speed: %s sizeBytes: %ld", speed.c_str(), sizeBytes);

    // Parse the speed string to get the download speed in bytes/s
    if (speed.find("MB") != std::string::npos)
    {
        downloadSpeed = std::stol(speed.substr(0, speed.find("MB") - 1)) * 1024 * 1024; // Convert MB/s to bytes/s
    }
    else if (speed.find("kB") != std::string::npos)
    {
        downloadSpeed = std::stol(speed.substr(0, speed.find("kB") - 1)) * 1024; // Convert kB/s to bytes/s
    }
    else if (speed.find("bytes") != std::string::npos)
    {
        downloadSpeed = std::stol(speed.substr(0, speed.find("bytes") - 1));
        if (downloadSpeed == 0)
        {
            downloadSpeed = 5 * 1024; // 当 speed 属于 0 bytes/s 时，代表不下载，但进度也应该有，因此默认为5*1024
                                      // = 5KB 计算时间
        }
    }
    else
    {
        if (sizeBytes < 169887)
        {
            return "00:10"; // 给出默认时间 10 秒
        }
        else
        {
            return "01:00"; // 给出默认时间 1 分钟
        }
    }
    kmlogger.debug("speed: %s sizeBytes: %ld downloadSpeed=%ld", speed.c_str(), sizeBytes, downloadSpeed);

    // if (isZero(downloadSpeed))
    if (downloadSpeed == 0 && sizeBytes > 0)
    {
        // return "";
        downloadSpeed = 5 * 1024; // 当 speed 属于 0 bytes/s 时，代表不下载，但进度也应该有，因此默认为50计算时间
    }

    // Calculate the remaining download time in seconds
    int downloadTime = (int)sizeBytes / downloadSpeed;
    kmlogger.debug("speed: %s sizeBytes: %ld downloadSpeed=%ld downloadTime=%d", speed.c_str(), sizeBytes, downloadSpeed, downloadTime);

    // Format the download time as hours:minutes:seconds or minutes:seconds
    if (downloadTime >= 3600)
    {
        int hours = static_cast<int>(downloadTime / 3600);
        int minutes = static_cast<int>((downloadTime % 3600) / 60);
        int seconds = static_cast<int>(downloadTime % 60);
        result = std::to_string(hours) + ":" + std::to_string(minutes) + ":" + std::to_string(seconds);
        kmlogger.debug("speed: %s sizeBytes: %ld downloadSpeed=%ld downloadTime=%d result:%s", speed.c_str(), sizeBytes, downloadSpeed, downloadTime, result.c_str());
    }
    else
    {
        int minutes = static_cast<int>(downloadTime / 60);
        int seconds = static_cast<int>(downloadTime % 60);
        result = std::to_string(minutes) + ":" + std::to_string(seconds);
        kmlogger.debug("speed: %s sizeBytes: %ld downloadSpeed=%ld downloadTime=%d result:%s", speed.c_str(), sizeBytes, downloadSpeed, downloadTime, result.c_str());
    }

    if (result.find("-") != std::string::npos)
    {
        // 时间为负数不合理，此处先默认给出5分钟
        return "05:00";
    }

    return result;
}

int KMPackageManager::deploy()
{
    fs::path basePath = d->m_folder->getPath();
    fs::path layersPath;

    kmlogger.info("部署开始");
    for (auto &downloadRef : d->m_pmRefDownloadList)
    {
        d->m_installedFiles.clear();

        if (downloadRef.ref.module == "devel")
        {
            layersPath = fs::path(KMStorageDir::getUserBaseDirLocation());
        }
        else
        {
            layersPath = basePath / "layers";
        }

        kmlogger.info("正在部署 completedRef: %s", downloadRef.completedRef.c_str());
        fs::path idPath = layersPath / downloadRef.ref.channel / downloadRef.ref.arch / downloadRef.ref.kind / downloadRef.ref.id;

        fs::path versionDataPath = layersPath / downloadRef.completedRef;
        kmlogger.debug("versionDataPath:  %s", versionDataPath.c_str());

        if (downloadRef.ref.kind == "app")
        {
            d->m_installedFiles.insert(idPath.string());
        }

        d->m_installedFiles.insert(versionDataPath.string());

        if (std::filesystem::exists(versionDataPath) || std::filesystem::create_directories(versionDataPath))
        {
            kmlogger.debug("Directory created or already exists successfully!");
        }

        // ostreeManager.checkout("f3b1314b51f2b8865089f13cbae5b7cd449b169f0b36530d27da74beb68aa492", "your-repo-path");
        kmlogger.debug("Begin to checkout ...");
        string latestCommit = d->m_ostreeHandler->readLatestCommit(downloadRef.completedRef);
        d->m_ostreeHandler->checkout(latestCommit, versionDataPath.string());
        // sremoveHardlinksInPlace(versionDataPath / "entries");

        kmlogger.debug("End to checkout.");
        kmlogger.info("baseType:  %s", downloadRef.ref.kind.c_str());

        d->m_hostAppDeploy->setHostAppConfig(versionDataPath, downloadRef.ref.id);
        if (d->m_hostAppDeploy->loadHostAppInfo())
        {
            d->m_isHostapp = true;
            d->m_hostAppDeploy->collectSynchronizedFiles();
            d->m_hostAppDeploy->processRecordedDesktopFiles(*this);

            try
            {
                d->m_hostAppDeploy->synchronizeFiles(false);
                KMInfo("Synchronization complete!");
            }
            catch (const std::exception &e)
            {
                KMError("Error during synchronization: " + std::string(e.what()));
            }
        }
        else if (downloadRef.ref.kind == "app")
        {
            KMInfoJson infoJson;
            fs::path infoPath = versionDataPath / "info.json";
            infoJson.loadFile(infoPath.string());

            downloadRef.ref.isSysapp = infoJson.annotations.sysapp;
            std::vector<std::string> plugins = infoJson.export_plugins;

            const bool isImmutableSystem = KMFileUtils::isImmutableSystem();
            const std::string userFilePath = isImmutableSystem ? "/opt/system/lib/systemd/user/" : "/usr/lib/systemd/user/";
            const std::string systemFilePath = isImmutableSystem ? "/opt/system/lib/systemd/system/" : "/usr/lib/systemd/system/";
            const std::string dbusFilePath = isImmutableSystem ? "/opt/system/resource/dbus-1/services" : "/usr/share/dbus-1/services";
            const std::string systemDbusFilePath = isImmutableSystem ? "/opt/system/resource/dbus-1/system-services" : "/usr/share/dbus-1/system-services";
            const std::string systemDbusPoliyPath = isImmutableSystem ? "/opt/system/conf/dbus-1/system.d" : "/etc/dbus-1/system.d";
            const std::string schemasFilePath = isImmutableSystem ? "/opt/system/resource/glib-2.0/schemas/" : "/usr/share/glib-2.0/schemas";
            // const std::string ukuiNotificationFilePath = isImmutableSystem ? "/opt/system/resource/ukui/ukui-notification/" : "/usr/share/ukui-notification/";
            const std::string ukuiNotificationFilePath = "/etc/ukui/ukui-notification/default-app/";
            kmlogger.info(isImmutableSystem ? "ImmutableSystem" : "Not ImmutableSystem");

            // modify service file
            fs::path serviceFileDirectoryPath = versionDataPath / "entries" / "usr" / "share" / "dbus-1" / "services";
            if (!fs::exists(serviceFileDirectoryPath))
            {
                serviceFileDirectoryPath = versionDataPath / "entries" / "share" / "dbus-1" / "services";
            }

            if (fs::exists(serviceFileDirectoryPath))
            {
                modifyServiceFile(downloadRef, serviceFileDirectoryPath.string(), dbusFilePath);
                // KMFileUtils::copyFilesByExtension(serviceFileDirectoryPath, dbusFilePath, ".service", "service");
            }

            // system-service
            fs::path systemServiceFileDirectoryPath = versionDataPath / "entries" / "usr" / "share" / "dbus-1" / "system-services";
            if (!fs::exists(systemServiceFileDirectoryPath))
            {
                systemServiceFileDirectoryPath = versionDataPath / "entries" / "share" / "dbus-1" / "system-services";
            }

            if (fs::exists(systemServiceFileDirectoryPath))
            {
                modifyServiceFile(downloadRef, serviceFileDirectoryPath.string(), systemDbusFilePath);
            }

            // system-service policy file
            fs::path systemdFileDirectoryPath = versionDataPath / "entries" / "usr" / "share" / "dbus-1" / "system.d";
            if (!fs::exists(systemdFileDirectoryPath))
            {
                systemdFileDirectoryPath = versionDataPath / "entries" / "share" / "dbus-1" / "system.d";
            }

            if (fs::exists(systemdFileDirectoryPath))
            {
                KMFileUtils::copyFilesByExtension(systemdFileDirectoryPath, dbusFilePath, ".conf", "service", d->m_installedFiles);
            }

            fs::path schemasSourceDir = versionDataPath / "entries" / "share" / "glib-2.0" / "schemas";
            if (fs::exists(schemasSourceDir))
            {
                fs::create_directories(schemasFilePath);
                KMFileUtils::copyFilesByExtension(schemasSourceDir, schemasFilePath, ".xml", "schema", d->m_installedFiles);

                std::string schemaCommand;
                schemaCommand = "glib-compile-schemas " + schemasFilePath + " >/dev/null 2>&1";
                int ret = system(schemaCommand.c_str());
                if (ret != 0)
                {
                    kmlogger.error("glib-compile-schemas failed for %s, return code: %d", schemasFilePath.c_str(), ret);
                }
            }

            fs::path systemPath;
            if (fs::exists(versionDataPath / "entries" / "etc" / "systemd"))
            {
                systemPath = versionDataPath / "entries" / "etc" / "systemd";
            }
            else if (fs::exists(versionDataPath / "entries" / "usr" / "lib" / "systemd"))
            {
                systemPath = versionDataPath / "entries" / "usr" / "lib" / "systemd";
            }

            auto buildSystemdPath = [](const fs::path &basePath, bool isSystem) -> fs::path
            {
                const char *subpath = isSystem ? "system" : "user";
                return basePath / subpath;
            };

            if (!systemPath.string().empty())
            {
                processServiceFiles(buildSystemdPath(systemPath, true), systemFilePath, downloadRef, d->m_installedFiles);
                processServiceFiles(buildSystemdPath(systemPath, false), userFilePath, downloadRef, d->m_installedFiles);
            }

            // Create binData file: entries/bin/ref.id
            fs::path binData;

            if (fs::exists(versionDataPath / "entries" / "usr"))
            {
                binData = versionDataPath / "entries" / "usr" / "bin";
            }
            else
            {
                binData = versionDataPath / "entries" / "bin";
            }

            kmlogger.debug("Check directory:  %s", binData.string().c_str());
            if (fs::exists(binData) || fs::create_directories(binData))
            {
                kmlogger.info("create diretory %s success", binData.string().c_str());
            }

            fs::path binDataRef = binData / downloadRef.ref.id;
            createExportBinShellScript(downloadRef, binDataRef.string());

            // 创建目标目录
            auto ensureDirExists = [](const fs::path &path)
            {
                if (!fs::exists(path))
                {
                    fs::create_directory(path);
                }
            };

            ensureDirExists(d->m_folder->getExportsPath());
            ensureDirExists(d->m_folder->getExportsSharePath());
            ensureDirExists(d->m_folder->getExportsBinPath());

            getAllAppFilesInDirectory(versionDataPath.string(), d->m_installedFiles, downloadRef.ref.id);

            // 递归遍历源目录export/并处理文件
            const std::string targetPath = d->m_folder->getPath().string();
            modifyExportsDirectory(downloadRef, (versionDataPath / "entries").string(), targetPath);
            kmlogger.debug("Exports files symlinked to /opt/kaiming/exports directory successfully.");

            if (fs::exists(versionDataPath / "entries" / "etc" / "ukui" / "ukui-notification" / "default-app"))
            {
                KMFileUtils::copyFilesByExtension(versionDataPath / "entries" / "etc" / "ukui" / "ukui-notification" / "default-app", ukuiNotificationFilePath, ".json", "ukui", d->m_installedFiles);
            }

            d->m_pmBinName.clear();

            // 生成应用desktop, icon, service等缓存
            const std::vector<std::string> triggerCachePaths = {
                "/opt/kaiming-tools/share/kaiming/shells/gtk-icon-cache.trigger",
                "/opt/kaiming-tools/share/kaiming/shells/mime-database.trigger",
                "/opt/kaiming-tools/share/kaiming/shells/desktop-database.trigger"};

            runMultiperTriggerUpdateCacheCommand(triggerCachePaths);

            KMPluginSynchronizer::syncPlugins(versionDataPath / "files", plugins);
        }

        // 修改文件夹属主为当前用户，处理 run 运行的权限问题
        // modifyDirOwnership(idPath);

        // if (downloadRef.ref.kind == "base")
        // {
        //     modifyBaseDir(versionDataPath);
        // }
        // Todo: Pruning repo: ostree_repo_prune()
        // 生成所有文件列表文件
        std::cout << "\nWaiting for generate " << downloadRef.name << "'s deploy file ..."
                  << "\n";

        if (downloadRef.ref.kind != "app")
        {
            getAllBaseFilesInDirectory(versionDataPath.string(), d->m_installedFiles);
        }

        fs::path deployDataFile = versionDataPath / "deploy";
        bool isDeploy = createInstalledFile(deployDataFile.string(), false);

        if (!isDeploy)
        {
            std::cout << "Generate installed deploy file failed!" << std::endl;
        }

        fs::path infoListFile = d->m_folder->getInfoPath() / (downloadRef.ref.id + ".list");
        writeInstalledFilesToList(infoListFile.string());

        const char *old_value = getenv("XDG_DATA_DIRS");
        std::string new_value = "/opt/system/resource";
        if (old_value)
        {
            new_value += ":";
            new_value += old_value;
        }
        else
        {
            new_value += ":/usr/local/share:/usr/share";
        }

        // 设置合并后的值
        setenv("XDG_DATA_DIRS", new_value.c_str(), 1);

        int result = system("exec 3>&1 1>/dev/null 2>&1; update-mime-database /opt/system/resource/mime");
        if (result != 0)
        {
            kmlogger.error("update-mime-database failed with code %d", result);
        }
        else
        {
            kmlogger.info("MIME database updated successfully");
        }
        // 存储已安装的开明包的信息到/opt/kaiming/info/kaiming.list
        fillInstalledInfo(downloadRef);
        writeInstalledInfoToList();

        std::set<std::string> deployfiles = d->m_hostAppDeploy->getSynchronizedFiles();
        d->m_installedFiles.merge(deployfiles);
        setKsafLabelAndExectl(d->m_installedFiles, downloadRef.ref.id, downloadRef.ref.kind, versionDataPath);

        if (downloadRef.ref.module == "devel")
        {
            KMStorageDir::modifyDirOwnership(KMStorageDir::getUserDevelDataDirLocation());
        }

        // 创建 deploy ref
        d->m_ostreeHandler->updateDeployRef(downloadRef.completedRef, latestCommit);

        // start services
        startTargetWantsServices(versionDataPath);
    }

    d->m_installedInfo.clear();
    d->m_pmDownloadRefs.clear();
    d->m_pmFuzzyMatchRefs.clear();
    d->m_pmRefDownloadList.clear();
    kmlogger.info("部署成功");

    return KM_ERROR_NO;
}

void KMPackageManager::writeInstalledInfoToList()
{
    fs::path filePath = d->m_folder->getInfoPath() / "kaiming.list";

    fs::path dirPath = fs::path(filePath).parent_path();

    if (!fs::exists(dirPath))
    {
        if (!fs::create_directories(dirPath))
        {
            KMError("Error creating directory: " + dirPath.string());
            return;
        }
    }

    // 使用 std::ios::app 模式打开文件以追加内容
    std::ofstream outFile(filePath, std::ios::app);

    if (!outFile)
    {
        KMError("Error opening file: " + filePath.string());
        return;
    }

    auto escapeNewlines = [](const std::string &input) -> std::string
    {
        std::string result;
        for (char ch : input)
        {
            if (ch == '\n')
                result += "\\n";
            else if (ch == '\r')
                result += "\\r";
            else
                result += ch;
        }
        return result;
    };

    for (const auto &[key, value] : d->m_installedInfo)
    {
        if (key == "Id")
        {
            std::cout << "Writing " << value << "'s information to " << filePath.string() << "..." << std::endl;
        }
        outFile << key << " : " << escapeNewlines(value) << "\n";
    }
    outFile << "\n";
    outFile.close();
}

void KMPackageManager::removePackageInfoFromList(const std::string &packageId, const std::string &version, const std::string &arch, const std::string &module)
{
    fs::path filePath = d->m_folder->getInfoPath() / "kaiming.list";
    if (!fs::exists(filePath))
    {
        KMError("File does not exist: " + filePath.string());
        return;
    }

    std::cout << "File exists: " << filePath.string() << ". Deleting " << packageId << "'s information..." << std::endl;

    std::ifstream inFile(filePath);
    if (!inFile)
    {
        KMError("Error opening file for reading: " + filePath.string());
        return;
    }

    std::stringstream buffer;
    std::string line;
    std::vector<std::string> block;

    while (std::getline(inFile, line))
    {
        if (line.empty())
        {
            // 检查块内是否匹配目标字段
            bool matchId = false, matchVersion = false, matchArch = false, matchModule = false;
            for (const auto &entry : block)
            {
                if (entry == "Id : " + packageId)
                    matchId = true;
                if (entry == "Version : " + version)
                    matchVersion = true;
                if (entry == "Arch : " + arch)
                    matchArch = true;
                if (entry == "Module : " + module)
                    matchModule = true;
            }

            if (!(matchId && matchVersion && matchArch && matchModule))
            {
                // 保留该块
                for (const auto &entry : block)
                {
                    buffer << entry << "\n";
                }
                buffer << "\n"; // 保留块之间的空行
            }

            block.clear();
        }
        else
        {
            block.push_back(line);
        }
    }

    // 处理最后一个 block（如果文件末尾没有空行）
    if (!block.empty())
    {
        bool matchId = false, matchVersion = false, matchArch = false;
        for (const auto &entry : block)
        {
            if (entry == "Id : " + packageId)
            {
                matchId = true;
            }
            if (entry == "Version : " + version)
            {
                matchVersion = true;
            }
            if (entry == "Arch : " + arch)
            {
                matchArch = true;
            }
        }

        if (!(matchId && matchVersion && matchArch))
        {
            for (const auto &entry : block)
            {
                buffer << entry << "\n";
            }
            buffer << "\n";
        }
    }

    inFile.close();

    // 写回文件
    std::ofstream outFile(filePath, std::ios::trunc);
    if (!outFile)
    {
        KMError("Error opening file for writing: " + filePath.string());
        return;
    }

    outFile << buffer.str();
    outFile.close();
}

/**
 * @brief 格式化文件大小
 *
 * @param size
 * @return string
 */
std::string KMPackageManager::formatFileSize(double size) const
{
    vector<string> units = {"B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"};
    int index = 0;

    while (size >= 1024.0 && index < units.size())
    {
        size /= 1024.0;
        index++;
    }

    std::ostringstream oss;
    oss << std::fixed << std::setprecision(1) << size << " " << units[index];
    return oss.str();
}

void KMPackageManager::fillInstalledInfo(const KMPMRef &downloadRef)
{
    d->m_installedInfo["Id"] = downloadRef.ref.id;
    d->m_installedInfo["Channel"] = downloadRef.ref.channel;
    d->m_installedInfo["Version"] = downloadRef.ref.version;
    d->m_installedInfo["Arch"] = downloadRef.ref.arch;
    d->m_installedInfo["Module"] = downloadRef.ref.module;
    d->m_installedInfo["Kind"] = downloadRef.ref.kind;
    d->m_installedInfo["InstalledSize"] = formatFileSize(downloadRef.installedSize);
    d->m_installedInfo["Name"] = downloadRef.name;
    d->m_installedInfo["Description"] = downloadRef.description;
    d->m_installedInfo["CompletedRef"] = downloadRef.completedRef;
}

KMEntry KMPackageManager::cutRef(const std::string &completeRef)
{
    std::stringstream ss(completeRef);
    std::string token;
    vector<std::string> tokens;

    while (std::getline(ss, token, '/'))
    {
        tokens.push_back(token); // 将切分后的部分添加到 tokens 向量中
    }

    int tokensSize = tokens.size();
    KMEntry entry;
    entry.id = tokens[tokensSize - 3];
    entry.version = tokens[tokensSize - 1];
    entry.arch = tokens[tokensSize - 5];
    entry.module = tokens[tokensSize - 2];
    entry.kind = tokens[tokensSize-4];
    return entry;
}

int KMPackageManager::deployOfflinePackage(std::map<std::string, string> &mountMap)
{
    fs::path basePath = d->m_folder->getPath();
    fs::path layersPath;

    uint64_t totalSize = 0;
    uint64_t preSize = 0;

    // 计算总的包大小
    for (auto &downloadRef : d->m_pmRefOfflineList)
    {
        totalSize += downloadRef.installedSize;
    }

    kmlogger.info("部署开始");
    for (auto &downloadRef : d->m_pmRefOfflineList)
    {
        std::cout << "正在部署离线包: " << downloadRef.ref.id << " ..." << std::endl;
        kmlogger.info("正在部署 completedRef: %s", downloadRef.completedRef.c_str());

        if (downloadRef.ref.module == "devel")
        {
            layersPath = fs::path(KMStorageDir::getUserBaseDirLocation());
        }
        else
        {
            layersPath = basePath / "layers";
        }

        fs::path idPath = layersPath / downloadRef.ref.channel / downloadRef.ref.arch / downloadRef.ref.kind / downloadRef.ref.id;

        fs::path versionDataPath = layersPath / downloadRef.completedRef;
        kmlogger.debug("versionDataPath:  %s", versionDataPath.c_str());
        d->m_installedFiles.clear();
        d->m_installedInfo.clear();

        // 存储已安装的开明包的信息到/opt/kaiming/info/kaiming.list
        fillInstalledInfo(downloadRef);
        writeInstalledInfoToList();

        if (downloadRef.ref.kind == "app")
        {
            d->m_installedFiles.insert(idPath.string());
        }

        d->m_installedFiles.insert(versionDataPath.string());

        if (std::filesystem::exists(versionDataPath) || std::filesystem::create_directories(versionDataPath))
        {
            kmlogger.debug("Directory created or already exists successfully!");
        }

        kmlogger.debug("Begin to copy data from mountpoint ...");
        fs::path mountValue = mountMap[downloadRef.ref.id + downloadRef.ref.module];
        fs::path mountpointModulePath = mountValue / "layers" / downloadRef.ref.id / downloadRef.ref.module;

        if (downloadRef.ref.isDeltas)
        {
            if (downloadRef.ref.preVersion.size() > 1)
            {
                mountpointModulePath = mountValue / "layers" / downloadRef.ref.id / downloadRef.ref.module / "files" / downloadRef.ref.findPreVersion / "files" / "layers" / downloadRef.ref.id / downloadRef.ref.module;
            }
            else
            {
                mountpointModulePath = mountValue / "layers" / downloadRef.ref.id / downloadRef.ref.module / "files" / "layers" / downloadRef.ref.id / downloadRef.ref.module;
            }
        }

        if (std::filesystem::exists(mountpointModulePath))
        {
            std::string sourcePath = KMUtil::escapePath(mountpointModulePath);
            std::string DestPath = KMUtil::escapePath(versionDataPath);
            std::string command = "rsync -a --progress " + sourcePath + " " + DestPath;

            FILE *pipe = popen(command.c_str(), "r");
            if (!pipe)
            {
                std::cerr << "Failed to run rsync command!" << std::endl;
                return 1;
            }

            int printNumber = -1;
            sharedValue = 0;
            // 启动线程来监控rsync的进度
            std::thread progressThread(KMPackageManager::monitorProgress, pipe);

            while (printNumber != 100)
            {
                if (downloadRef.installedSize > 0)
                {
                    int currentValue = sharedValue.load(std::memory_order_relaxed);
                    if (currentValue > printNumber)
                    {
                        printNumber = currentValue;
                        // 当前百分比等于已安装的+正在安装*当前包所占百分比
                        //  std::string printValue =std::to_string(preSize + (currentValue * downloadRef.installedSize / totalSize));
                        std::cout << "\r" << currentValue << "%" << std::flush;
                        progressJson = KMDbusJson::packProgressOffInfoToJson(downloadRef.ref.id, currentValue);
                        updateProgress();
                    }
                }

                if (feof(pipe))
                {
                    std::cout << "\r"
                              << "100%" << std::flush;
                    progressJson = KMDbusJson::packProgressOffInfoToJson(downloadRef.ref.id, 100);
                    updateProgress();
                    break;
                }
                std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 适当间隔去获取值，避免过于频繁占用资源
            }

            // 等待进度监控线程和进度条线程完成
            progressThread.join();

            // 关闭管道
            fclose(pipe);

            kmlogger.debug("Data copied from mountpoint successfully.");
        }
        else
        {
            kmlogger.error("mountpointModulePath not exists:  %s", mountpointModulePath.string().c_str());
        }

        //根据二进制文件同步最新文件
        if (downloadRef.ref.isDeltas)
        {
            fs::path preIdPath = layersPath / downloadRef.ref.channel / downloadRef.ref.arch / downloadRef.ref.kind / downloadRef.ref.id / downloadRef.ref.module /downloadRef.ref.findPreVersion;
            upgradeDirectory(versionDataPath, preIdPath);

        }

        kmlogger.debug("End to copy data from mountpoint.");
        kmlogger.info("baseType:  %s", downloadRef.ref.kind.c_str());

        d->m_hostAppDeploy->setHostAppConfig(versionDataPath, downloadRef.ref.id);
        if (d->m_hostAppDeploy->loadHostAppInfo())
        {
            d->m_isHostapp = true;
            d->m_hostAppDeploy->collectSynchronizedFiles();
            d->m_hostAppDeploy->processRecordedDesktopFiles(*this);

            try
            {
                d->m_hostAppDeploy->synchronizeFiles(downloadRef.ref.isDeltas);
                KMInfo("Synchronization complete!");
            }
            catch (const std::exception &e)
            {
                KMError("Error during synchronization: " + std::string(e.what()));
            }
        }
        else if (downloadRef.ref.kind == "app")
        {
            const bool isImmutableSystem = KMFileUtils::isImmutableSystem();
            const std::string userFilePath = isImmutableSystem ? "/opt/system/lib/systemd/user/" : "/usr/lib/systemd/user/";
            const std::string systemFilePath = isImmutableSystem ? "/opt/system/lib/systemd/system/" : "/usr/lib/systemd/system/";
            const std::string dbusFilePath = isImmutableSystem ? "/opt/system/resource/dbus-1/services" : "/usr/share/dbus-1/services";
            const std::string systemDbusFilePath = isImmutableSystem ? "/opt/system/resource/dbus-1/system-services" : "/usr/share/dbus-1/system-services";
            const std::string systemDbusPoliyPath = isImmutableSystem ? "/opt/system/conf/dbus-1/system.d" : "/etc/dbus-1/system.d";
            const std::string schemasFilePath = isImmutableSystem ? "/opt/system/resource/glib-2.0/schemas/" : "/usr/share/glib-2.0/schemas";
            // const std::string ukuiNotificationFilePath = isImmutableSystem ? "/opt/system/resource/ukui/ukui-notification/" : "/usr/share/ukui-notification/";
            const std::string ukuiNotificationFilePath = "/etc/ukui/ukui-notification/default-app/";
            kmlogger.info(isImmutableSystem ? "ImmutableSystem" : "Not ImmutableSystem");

            // modify service file
            fs::path serviceFileDirectoryPath = versionDataPath / "entries" / "usr" / "share" / "dbus-1" / "services";
            if (!fs::exists(serviceFileDirectoryPath))
            {
                serviceFileDirectoryPath = versionDataPath / "entries" / "share" / "dbus-1" / "services";
            }

            if (fs::exists(serviceFileDirectoryPath))
            {
                modifyServiceFile(downloadRef, serviceFileDirectoryPath.string(), dbusFilePath);
                // KMFileUtils::copyFilesByExtension(serviceFileDirectoryPath, dbusFilePath, ".service", "service");
            }

            // system-service
            fs::path systemServiceFileDirectoryPath = versionDataPath / "entries" / "usr" / "share" / "dbus-1" / "system-services";
            if (!fs::exists(systemServiceFileDirectoryPath))
            {
                systemServiceFileDirectoryPath = versionDataPath / "entries" / "share" / "dbus-1" / "system-services";
            }

            if (fs::exists(systemServiceFileDirectoryPath))
            {
                modifyServiceFile(downloadRef, systemServiceFileDirectoryPath.string(), systemDbusFilePath);
            }

            // system-service policy file
            fs::path systemdFileDirectoryPath = versionDataPath / "entries" / "usr" / "share" / "dbus-1" / "system.d";
            if (!fs::exists(systemdFileDirectoryPath))
            {
                systemdFileDirectoryPath = versionDataPath / "entries" / "share" / "dbus-1" / "system.d";
            }

            if (fs::exists(systemdFileDirectoryPath))
            {
                KMFileUtils::copyFilesByExtension(systemdFileDirectoryPath, systemDbusPoliyPath, ".conf", "service", d->m_installedFiles);
            }

            fs::path schemasSourceDir = versionDataPath / "entries" / "share" / "glib-2.0" / "schemas";
            if (fs::exists(schemasSourceDir))
            {
                fs::create_directories(schemasFilePath);
                KMFileUtils::copyFilesByExtension(schemasSourceDir, schemasFilePath, ".xml", "schema", d->m_installedFiles);

                std::string schemaCommand;
                schemaCommand = "glib-compile-schemas " + schemasFilePath + " >/dev/null 2>&1";
                int ret = system(schemaCommand.c_str());
                if (ret != 0)
                {
                    kmlogger.error("glib-compile-schemas failed for %s, return code: %d", schemasFilePath.c_str(), ret);
                }
            }

            fs::path systemPath;
            if (fs::exists(versionDataPath / "entries" / "etc" / "systemd"))
            {
                systemPath = versionDataPath / "entries" / "etc" / "systemd";
            }
            else if (fs::exists(versionDataPath / "entries" / "usr" / "lib" / "systemd"))
            {
                systemPath = versionDataPath / "entries" / "usr" / "lib" / "systemd";
            }

            auto buildSystemdPath = [](const fs::path &basePath, bool isSystem) -> fs::path
            {
                const char *subpath = isSystem ? "system" : "user";
                return basePath / subpath;
            };

            if (!systemPath.string().empty())
            {
                processServiceFiles(buildSystemdPath(systemPath, true), systemFilePath, downloadRef, d->m_installedFiles);
                processServiceFiles(buildSystemdPath(systemPath, false), userFilePath, downloadRef, d->m_installedFiles);
            }
            // Create binData file: entries/bin/ref.id
            fs::path binData;

            if (fs::exists(versionDataPath / "entries" / "usr"))
            {
                binData = versionDataPath / "entries" / "usr" / "bin";
            }
            else
            {
                binData = versionDataPath / "entries" / "bin";
            }
            kmlogger.debug("Check directory:  %s", binData.string().c_str());
            if (fs::exists(binData) || fs::create_directories(binData))
            {
                kmlogger.info("create diretory %s success", binData.string().c_str());
            }

            fs::path binDataRef = binData / downloadRef.ref.id;
            createExportBinShellScript(downloadRef, binDataRef.string());

            // 创建目标目录
            auto ensureDirExists = [](const fs::path &path)
            {
                if (!fs::exists(path))
                {
                    fs::create_directory(path);
                }
            };

            ensureDirExists(d->m_folder->getExportsPath());
            ensureDirExists(d->m_folder->getExportsSharePath());
            ensureDirExists(d->m_folder->getExportsBinPath());
            getAllAppFilesInDirectory(versionDataPath.string(), d->m_installedFiles, downloadRef.ref.id);

            // 递归遍历源目录export/并处理文件
            const std::string targetPath = d->m_folder->getPath().string();
            modifyExportsDirectory(downloadRef, (versionDataPath / "entries").string(), targetPath);
            kmlogger.debug("Exports files symlinked to /opt/kaiming/exports directory successfully.");

            if (downloadRef.ref.isDeltas)
            {
                fs::path deletePath = mountValue / "layers" / downloadRef.ref.id / downloadRef.ref.module / "files" / "delete.txt";
                if (downloadRef.ref.preVersion.size() > 1)
                {
                    deletePath = mountValue / "layers" / downloadRef.ref.id / downloadRef.ref.module / "files" / downloadRef.ref.findPreVersion / "files" / "delete.txt";
                }
                processDeleteFile(deletePath.string(),downloadRef.ref);
                fs::path preIdPath = layersPath / downloadRef.ref.channel / downloadRef.ref.arch / downloadRef.ref.kind / downloadRef.ref.id / downloadRef.ref.module /downloadRef.ref.findPreVersion;

                copyDirectory(versionDataPath, preIdPath);
                fs::remove_all(versionDataPath);  // 先删除目标目录

                auto tempPath = versionDataPath.string();
                // 现在可以安全重命名
                if (std::rename(preIdPath.c_str(), tempPath.c_str()) != 0) {
                    std::cerr << "重命名失败: " << strerror(errno) << std::endl;
                    // 处理错误
                }
            }

            if (fs::exists(versionDataPath / "entries" / "etc" / "ukui" / "ukui-notification" / "default-app"))
            {
                KMFileUtils::copyFilesByExtension(versionDataPath / "entries" / "etc" / "ukui" / "ukui-notification" / "default-app", ukuiNotificationFilePath, ".json", "ukui", d->m_installedFiles);
            }

            d->m_pmBinName.clear();

            // 生成应用desktop, icon, service等缓存
            const std::vector<std::string> triggerCachePaths = {
                "/opt/kaiming-tools/share/kaiming/shells/gtk-icon-cache.trigger",
                "/opt/kaiming-tools/share/kaiming/shells/mime-database.trigger",
                "/opt/kaiming-tools/share/kaiming/shells/desktop-database.trigger"};

            runMultiperTriggerUpdateCacheCommand(triggerCachePaths);

            KMPluginSynchronizer::syncPlugins(versionDataPath / "files", downloadRef.ref.vecPlugins);
        }

        // 修改文件夹属主为当前用户，处理 run 运行的权限问题
        // modifyDirOwnership(idPath);

        // if (downloadRef.ref.kind == "base")
        // {
        //     modifyBaseDir(versionDataPath);
        // }

        // 生成所有文件列表文件
        std::cout << "\nWaiting for generate " << downloadRef.name << "'s deploy file ..."
                  << "\n";

        if (downloadRef.ref.kind != "app")
        {
            getAllBaseFilesInDirectory(versionDataPath.string(), d->m_installedFiles);
        }

        fs::path deployDataFile = versionDataPath / "deploy";

        bool isDeploy = createInstalledFile(deployDataFile.string(), downloadRef.ref.isDeltas);

        if (!isDeploy)
        {
            std::cout << "Generate installed deploy file failed!" << std::endl;
        }

        fs::path infoListFile = d->m_folder->getInfoPath() / (downloadRef.ref.id + ".list");
        writeInstalledFilesToList(infoListFile.string());

        const char *old_value = getenv("XDG_DATA_DIRS");
        std::string new_value = "/opt/system/resource";
        if (old_value)
        {
            new_value += ":";
            new_value += old_value;
        }
        else
        {
            new_value += ":/usr/local/share:/usr/share";
        }

        // 设置合并后的值
        setenv("XDG_DATA_DIRS", new_value.c_str(), 1);

        int result = system("exec 3>&1 1>/dev/null 2>&1; update-mime-database /opt/system/resource/mime");
        if (result != 0)
        {
            kmlogger.error("update-mime-database failed with code %d", result);
        }
        else
        {
            kmlogger.info("MIME database updated successfully");
        }

        std::set<std::string> deployfiles = d->m_hostAppDeploy->getSynchronizedFiles();
        d->m_installedFiles.merge(deployfiles);
        setKsafLabelAndExectl(d->m_installedFiles, downloadRef.ref.id, downloadRef.ref.kind, versionDataPath);
        if (downloadRef.ref.module == "devel")
        {
            KMStorageDir::modifyDirOwnership(KMStorageDir::getUserDevelDataDirLocation());
        }

        // start services
        startTargetWantsServices(versionDataPath);

        // Todo: Pruning repo: ostree_repo_prune()
        std::cout << "成功部署离线包: " << downloadRef.ref.id << " " << std::endl;
    }

    // std::cout << "100%" << std::endl;
    progressJson = "100%";
    updateProgress();

    d->m_okFile->umountOK();
    d->m_pmDownloadRefs.clear();
    d->m_pmFuzzyMatchRefs.clear();
    d->m_pmRefDownloadList.clear();
    kmlogger.info("部署成功");

    return KM_ERROR_NO;
}

void KMPackageManager::createFileForEmptyString(const std::string &filename)
{
    // 打开文件进行检查
    std::ifstream inputFile(filename);
    if (inputFile.is_open())
    {
        kmlogger.error("File already exists:  %s", filename.c_str());
        inputFile.close();
        return;
    }

    // 创建文件并打开输出流
    std::ofstream outputFile(filename);
    if (!outputFile.is_open())
    {
        kmlogger.error("Failed to create file:  %s", filename.c_str());
        return;
    }

    // 写入空字符串到文件
    outputFile << "";

    // 关闭文件
    outputFile.close();
}

void KMPackageManager::modifyServiceFile(KMPMRef &pmRef, const string &serviceFileDirectoryPath, const string destPath)
{
    std::vector<std::string> files;
    files.clear();

    bool noModifyServiceFileFlag = false;

    if (!fs::exists(destPath))
    {
        fs::create_directories(destPath); // 创建单级目录
    }

    // 调用函数获取目录下所有文件
    bool success = getAllFilesInDirectory(serviceFileDirectoryPath, files);
    if (success)
    {
        for (const auto &file : files)
        {
            if (file.find(".service") != std::string::npos)
            {
                string serviceFileName = file;
                kmlogger.debug("serviceFileName:  %s", serviceFileName.c_str());

                std::vector<std::string> serviceDatas = getDataFromKVFile(serviceFileName);

                for (auto &line : serviceDatas)
                {
                    // 修改 Exec 字段
                    size_t eqPos = line.find("Exec=");
                    if (eqPos != std::string::npos && eqPos == 0)
                    {
                        std::string value = line.substr(eqPos + strlen("Exec="));
                        if (value.find(" run") != std::string::npos)
                        {
                            // 第一次已进行修改，因此不修改当前文件
                            noModifyServiceFileFlag = true;
                        }

                        string serviceExec = "Exec=";
                        string content;

                        if (pmRef.ref.isSysapp)
                        {
                            content = serviceExec.append("/opt/kaiming-tools/bin/kaiming run ").append(" ").append("--command=").append(value).append(" ").append(pmRef.ref.id);
                        }
                        else
                        {
                            size_t lastPos = value.find_last_of('/');
                            std::string posValue = (lastPos == std::string::npos) ? value : value.substr(lastPos + 1);
                            content = serviceExec.append("/opt/kaiming-tools/bin/kaiming run ").append(" ").append("--command=").append("/opt/apps/").append(pmRef.ref.id).append("/files/bin/").append(posValue).append(" ").append(pmRef.ref.id);
                        }

                        line = content;
                    }
                }

                size_t lastSlashPos = serviceFileName.find_last_of('/');
                std::string filename = serviceFileName.substr(lastSlashPos + 1);
                std::string dest = destPath + '/' + filename;
                setDataToKVFile(dest, serviceDatas);
                d->m_installedFiles.insert(dest);
                // if (!noModifyServiceFileFlag)
                // {
                //     // 将修改后的内容写回 .service 文件
                //     if (setDataToKVFile(serviceFileName, serviceDatas))
                //     {
                //         kmlogger.debug("Desktop file modified successfully.");
                //     }
                // }
            }
        }
    }
    else
    {
        kmlogger.error("Failed to get files in directory.");
    }
}

void KMPackageManager::initializeFixedModifications()
{
    fixedModifications = {
        {"ExecReload", [this](const auto &s, const auto &id)
         { return addOkPrefix(s, id); }},
        {"ExecStartPre", [this](const auto &s, const auto &id)
         { return addOkPrefix(s, id); }},
        {"ExecStart", [this](const auto &s, const auto &id)
         { return formatExecStart(s, id); }},
        {"Type", "simple"},
        {"CapabilityBoundingSet", "CAP_NET_BIND_SERVICE"},
        {"NoNewPrivileges", "false"},
        {"PrivateUsers", "false"},
        {"ProtectControlGroups", "false"},
        {"ProtectHostname", "false"},
        {"ProtectKernelLogs", "false"},
        {"ProtectProc", "invisible"},
        {"RestrictAddressFamilies", ""},
        {"RestrictNamespaces", "false"},
        {"SystemCallArchitectrues", "native"},
        {"SystemCallFilter", ""},
        {"NoExecPaths", ""},
        {"TasksMax", [this](const auto &s, const auto &id)
         { return changeTasks(s); }},
        {"KillMode", "control-group"}};
}

vector<string> KMPackageManager::getServiceName(const vector<string> &files)
{
    vector<string> servicesFiles;
    for (const auto &file : files)
    {
        if (file.find(".service") != std::string::npos)
        {
            kmlogger.debug("serviceFileName:  %s", file.c_str());
            servicesFiles.push_back(file);
        }
    }
    return servicesFiles;
}

string KMPackageManager::addOkPrefix(const string &original, const std::string id)
{
    return "/opt/kaiming-tools/bin/kaiming run --detach=false --command=\"" + original + "\" " + id;
}

string KMPackageManager::addKillPrefix(const string &original, const std::string id)
{
    return "/opt/kaiming-tools/bin/kaiming kill " + id;
}

string KMPackageManager::changeTasks(const string &original)
{
    if (original == "infinity")
    {
        return "512";
    }
    return original;
}

string KMPackageManager::formatExecStart(const std::string &line, const std::string id)
{
    std::string value = line;
    bool need = false;
    if (!value.empty() && value.front() == '"')
        value = value.substr(1);
    if (!value.empty() && value.back() == '"')
        value.pop_back();

    if (!value.empty() && value.front() == '-')
    {
        value = value.substr(1);
        need = true;
    }

    // 保留 `--supervised systemd --daemonize no`（如果存在）
    std::string extraArgs;
    size_t supervisedPos = value.find("--supervised systemd");
    size_t daemonizePos = value.find("--daemonize no");
    if (supervisedPos != std::string::npos && daemonizePos != std::string::npos)
    {
        extraArgs = " --supervised systemd --daemonize no";
        // 移除 "--supervised systemd" 和 "--daemonize no"
        value.erase(supervisedPos, std::string("--supervised systemd").length());
        // 移除可能出现的多余空格
        while (supervisedPos < value.length() && value[supervisedPos] == ' ')
        {
            value.erase(supervisedPos, 1);
        }
        daemonizePos = value.find("--daemonize no");
        if (daemonizePos != std::string::npos)
        {
            value.erase(daemonizePos, std::string("--daemonize no").length());
            // 移除可能出现的多余空格
            while (daemonizePos < value.length() && (value[daemonizePos] == ' ' || value[daemonizePos - 1] == ' '))
            {
                value.erase(daemonizePos, 1);
            }
        }
    }

    if (need)
    {
        return "-/opt/kaiming-tools/bin/kaiming run --detach=false --command=\"" + value + " " + extraArgs + "\" " + id;
    }

    return "/opt/kaiming-tools/bin/kaiming run --detach=false --command=\"" + value + " " + extraArgs + "\" " + id;
}

bool KMPackageManager::isField(const string &line, const string &field)
{
    return line.rfind(field + "=", 0) == 0;
}

string KMPackageManager::modifyFixedField(const string &line, const string id)
{
    static const std::unordered_set<std::string> commentFileds = {
        "CapabilityBoundingSet",
        "ProtectKernelTunables",
        "ProtectSystem",
        "User",
        "Group",
        "ExecStop",
        "ProtectHome",
        "ProtectSystem",
        "ProtectKernelTunables",
        "ExecPaths"};

    for (const auto &field : commentFileds)
    {
        if (isField(line, field))
        {
            return "#" + line; // 直接注释掉
        }
    }

    for (const auto &[field, modifier] : fixedModifications)
    {
        if (isField(line, field))
        {
            size_t equalPos = line.find('=');
            string originalValue = (equalPos != string::npos) ? line.substr(equalPos + 1) : "";

            if (holds_alternative<CallbackFunc>(modifier))
            {
                // 如果是回调函数，调用它
                CallbackFunc callback = get<CallbackFunc>(modifier);
                string newValue = callback(originalValue, id);
                return field + "=" + newValue;
            }
            else
            {
                // 如果是固定值
                string newValue = get<string>(modifier);
                return field + "=" + newValue;
            }
        }
    }
    return line; // 不修改
}

void KMPackageManager::modifyAppServiceFile(KMPMRef &pmRef, string serviceFile, string destPath)
{
    bool noModifyServiceFileFlag = false;

    std::vector<std::string> serviceDatas = getDataFromKVFile(serviceFile);

    bool inServiceSection = false;
    bool hasUser = false;
    bool hasGroup = false;
    size_t serviceSectionEnd = 0;

    for (size_t i = 0; i < serviceDatas.size(); ++i)
    {
        auto &currentLine = serviceDatas[i];
        if (currentLine.empty() || currentLine[0] == '#')
        {
            continue;
        }

        // 检查是否进入[Service]部分
        if (currentLine == "[Service]")
        {
            inServiceSection = true;
            serviceSectionEnd = i + 1;
            continue;
        }

        // 只在[Service]部分中修改
        if (inServiceSection)
        {
            string modifiedLine = modifyFixedField(currentLine, pmRef.ref.id);
            if (modifiedLine != currentLine)
            {
                currentLine = modifiedLine;
            }
        }
    }

    if (inServiceSection)
    {
        // 直接在服务段末尾插入这三个字段
        serviceDatas.insert(serviceDatas.begin() + serviceSectionEnd, "User=root");
        serviceDatas.insert(serviceDatas.begin() + serviceSectionEnd + 1, "Group=root");
        serviceDatas.insert(serviceDatas.begin() + serviceSectionEnd + 2, "ExecStop=" + addKillPrefix("", pmRef.ref.id));

        // 更新服务段结束位置（增加了3行）
        serviceSectionEnd += 3;
    }

    fs::path dest = destPath;

    if (!fs::exists(dest.parent_path()))
    {
        if (fs::create_directories(dest.parent_path()))
        {
            if (setDataToKVFile(dest, serviceDatas))
            {
                kmlogger.debug("Service file modified successfully.");
            }
            else
            {
                kmlogger.error("Failed to get files in directory.");
            }
        }
    }
    else
    {
        if (setDataToKVFile(dest, serviceDatas))
        {
            kmlogger.debug("Service file modified successfully.");
        }
        else
        {
            kmlogger.error("Failed to get files in directory.");
        }
    }
}

bool KMPackageManager::getAllFilesInDirectory(const std::string &directoryPath, std::vector<std::string> &files)
{
    try
    {
        // 遍历目录中的文件
        for (const auto &entry : fs::recursive_directory_iterator(directoryPath, fs::directory_options::skip_permission_denied | fs::directory_options::follow_directory_symlink))
        {
            if (fs::is_symlink(entry.path()) && fs::read_symlink(entry.path()) == entry.path())
            {
                continue;
            }

            // 将文件路径添加到文件列表中
            files.push_back(entry.path().string());
        }

        return true; // 成功获取文件列表
    }
    catch (const std::exception &e)
    {
        kmlogger.error("Failed to get files: %s", e.what());
        return false; // 获取文件列表失败
    }
}

bool KMPackageManager::getAllAppFilesInDirectory(const std::string &directoryPath, std::set<std::string> &files, const std::string &id)
{
    static const std::vector<std::string> binDirs = {
        "files/bin", "files/local/bin", "files/usr/bin", "files/usr/local", "files/opt"
    };

    KMInfoJson infoJson;
    const std::string jsonPath = directoryPath + "/" + "info.json";
    infoJson.loadFile(jsonPath);
    bool isSysapp = infoJson.getAnnotations().sysapp;

    const std::string infoDir = d->m_folder->getInfoPath();
    fs::create_directories(infoDir);

    std::vector<std::pair<std::string, std::string>> vecExecRecords;
    const fs::path dirPath(directoryPath);
    const std::string appPrefix = "/opt/apps/" + id + "/files";

    try
    {
        std::vector<fs::path> fullBinPaths;
        for (const auto &subdir : binDirs)
        {
            fullBinPaths.push_back(dirPath / subdir);
        }

        // 用于检测循环符号链接的已访问目录集合
        std::set<std::string> visitedDirs;

        for (auto it = fs::recursive_directory_iterator( dirPath, fs::directory_options::skip_permission_denied | fs::directory_options::follow_directory_symlink);
                                                            it != fs::recursive_directory_iterator(); ++it)
        {
            try
            {
                // 检测并跳过符号链接循环
                if (fs::is_directory(it->symlink_status()))
                {
                    auto realPath = fs::weakly_canonical(it->path()).string();
                    if (!visitedDirs.insert(realPath).second)
                    {
                        it.disable_recursion_pending(); // 已访问过，跳过
                        continue;
                    }
                }

                // 跳过自引用符号链接
                if (fs::is_symlink(it->path()) && fs::read_symlink(it->path()) == it->path())
                {
                    continue;
                }

                const auto &path = it->path();
                const auto pathStr = path.string();

                files.insert(pathStr);

                auto perms = fs::symlink_status(path).permissions();
                if ((perms & fs::perms::owner_exec) == fs::perms::none && (perms & fs::perms::group_exec) == fs::perms::none && (perms & fs::perms::others_exec) == fs::perms::none)
                {
                    continue; // 没有执行权限，直接跳过
                }

                if (KMFileUtils::isNonExecExt(path) || !KMFileUtils::isExecutableByFileCmd(path))
                {
                    continue;
                }

                // 检查是否在 bin 路径内
                for (const auto &binPath : fullBinPaths)
                {
                    if (pathStr.find(binPath.string()) == 0)
                    {
                        const std::string execName = path.filename().string();
                        fs::path linkPath;

                        if (binPath.filename() == "opt" && KMFileUtils::isShellScriptByFileCmd(path))
                        {
                            std::string strId = id + "_shellscript";
                            linkPath = fs::path(KAIMING_BIN_PATH) / strId / execName;
                            fs::create_directories(linkPath.parent_path());
                            d->m_pmBinName.push_back(linkPath);
                        }
                        else
                        {
                            linkPath = fs::path(KAIMING_BIN_PATH) / execName;
                            d->m_pmBinName.push_back(execName);
                        }

                        if (fs::exists(linkPath))
                        {
                            fs::remove(linkPath);
                        }
                        fs::create_symlink(KAIMING_PROGRESS_FULL_PATH, linkPath);
                        d->m_installedFiles.insert(linkPath);

                        std::string relPath;
                        const auto pos = pathStr.find("files");
                        relPath = (pos != std::string::npos) ? pathStr.substr(pos + 5) : path.filename().string();
                        if (!isSysapp)
                        {
                            relPath = appPrefix + relPath;
                        }
                        vecExecRecords.emplace_back(std::move(relPath), id);
                        break;
                    }
                }
            }
            catch (const std::exception &ex)
            {
                kmlogger.warn("跳过路径 %s: %s", it->path().string().c_str(), ex.what());
                it.disable_recursion_pending();
                continue;
            }
        }

        // 写入 bin 记录文件
        const std::string infoFile = (fs::path(infoDir) / (id + ".bin")).string();
        std::ofstream ofs(infoFile, std::ios::out | std::ios::trunc);
        if (ofs)
        {
            for (const auto &kv : vecExecRecords)
            {
                ofs << kv.first << " " << kv.second << "\n";
            }
        }

        return true;
    }
    catch (const std::exception &e)
    {
        kmlogger.error("Failed to get files: %s", e.what());
        return false;
    }
}

bool KMPackageManager::getAllBaseFilesInDirectory(const std::string &directoryPath, std::set<std::string> &files)
{
    try
    {
        // 遍历目录中的文件
        for (const auto &entry : fs::recursive_directory_iterator(directoryPath, fs::directory_options::skip_permission_denied))
        {
            if (fs::is_symlink(entry.path()) && fs::read_symlink(entry.path()) == entry.path())
            {
                continue;
            }

            // 将文件路径添加到文件列表中
            files.insert(entry.path().string());
        }

        return true; // 成功获取文件列表
    }
    catch (const std::exception &e)
    {
        kmlogger.error("Failed to get files: %s", e.what());
        return false; // 获取文件列表失败
    }
}

std::vector<std::string> KMPackageManager::getDataFromKVFile(const std::string &filename)
{
    std::vector<std::string> lines;
    std::ifstream file(filename);
    if (file.is_open())
    {
        std::string line;
        while (std::getline(file, line))
        {
            lines.push_back(line);
        }
        file.close();
    }
    else
    {
        kmlogger.error("Failed to open file::  %s", filename.c_str());
    }
    return lines;
}

bool KMPackageManager::setDataToKVFile(const std::string &filename, const std::vector<std::string> &newLines)
{
    std::ofstream file(filename);
    if (file.is_open())
    {
        for (const auto &line : newLines)
        {
            file << line << std::endl;
        }
        file.close();
        return true;
    }
    else
    {
        kmlogger.error("inFailed to open file for writingdex:  %s", filename.c_str());
        return false;
    }
}

void KMPackageManager::modifyDesktopFile(KMPMRef &pmRef, string exportDesktopFilePath, const string exportPath)
{
    kmlogger.info("Begin to exportDesktopFilePath: %s\n", exportDesktopFilePath.c_str());
    std::vector<std::string> desktopDatas = getDataFromKVFile(exportDesktopFilePath);

    bool needAddKaimingTag = false;
    // std::string baseName;

    // for (auto line : desktopDatas)
    // {
    //     if (line.find("Name=") == 0)
    //     {
    //         baseName = line.substr(strlen("Name="));
    //         break;
    //     }
    // }
    // 遍历 desktopDatas 通过每行 line 修改需要的字段
    for (size_t i = 0; i < desktopDatas.size();)
    {
        std::string &line = desktopDatas[i];
        // 跳过开头为 # 的注释字段
        if (line[0] == '#')
        {
            i++;
            continue;
        }

        // 注释以下内容处理无图标或开始菜单无法点击运行问题
        std::vector<std::string> annotationVector = {
            "DBusActivatable", // 注释 DBusActivatable 字段，否则org.gnome.Sudoku包任务栏无图标
            "StartupNotify",   // 注释 StartupNotify 字段，否则org.gnome.Aisleriot包任务栏无图标
            "TryExec",         // 注释 TryExec 字段，否则org.gnome.Gitg和org.ggsoft.etw在开始菜单无法点击运行
            "StartupWMClass="};

        // 检查是否已经存在StartupWMClass字段
        bool hasStartupWMClass = false;
        for (const auto& line: desktopDatas)
        {
            if (line.find("StartupWMClass=") == 0)
            {
                hasStartupWMClass = true;
                break;
            }
        }

        bool needAnnotation = false;
        for (auto it = annotationVector.begin(); it != annotationVector.end(); ++it)
        {
            if (line.find(*it) == 0)
            {
                needAnnotation = true;
                break;
            }
        }

        if (needAnnotation && !hasStartupWMClass)
        {
            line = "# " + line;
            i++;
            continue;
        }

        // 修改 Exec 字段，否则开始菜单应用运行不起来
        string serviceExec = "Exec=";
        size_t eqPos = line.find("Exec=");

        if (eqPos != std::string::npos && eqPos == 0)
        {
            std::string value = line.substr(eqPos + strlen("Exec="));
            bool modified = false;
            string content;
            // if (!d->m_pmBinName.empty())
            // {
            //     for (auto binName : d->m_pmBinName)
            //     {
            //         std::string fileName;
            //         if (binName.find('/')!= std::string::npos)
            //         {
            //             std::filesystem::path p(binName);
            //             fileName = p.filename().string();
            //         }
            //         else
            //         {
            //             fileName = binName;
            //         }

            //         if (line.find(fileName)!= std::string::npos)
            //         {
            //             // 找到第一个空格的位置
            //             size_t spacePos = line.find(' ', 5); // 从"Exec="后的位置开始搜索
            //             if (spacePos != string::npos) {
            //                 // 替换空格前的内容
            //                 content = "Exec=" + binName + line.substr(spacePos);
            //             }
            //             else
            //             {
            //                 content = serviceExec.append(binName);
            //             }
            //             modified = true;
            //             break;
            //         }
            //     }
            // }

            // 提取 basename（如 /opt/apps/cn.kdocs.kdesktop/files/bin/kdesktop → kdesktop）

            auto extractBasename = [](const std::string &s)
            {
                size_t lastSlash = s.rfind('/');
                std::string name = (lastSlash == std::string::npos) ? s : s.substr(lastSlash + 1);
                size_t space = name.find(' ');
                return (space == std::string::npos) ? name : name.substr(0, space);
            };
            size_t commandPos = value.find("--command=");
            std::string baseName = (commandPos != std::string::npos)
                                       ? extractBasename(value.substr(commandPos + strlen("--command=")))
                                       : extractBasename(value);

            if (value.find(" run") == std::string::npos)
            {
                std::string formatExec = d->m_util->formatExecString(value, pmRef.ref.id);
                kmlogger.info("formatExec: %s", formatExec.c_str());
                line = "Exec=/opt/kaiming-tools/bin/kaiming run " + formatExec;
            }
            else
            {
                size_t pos = line.find("/usr/bin/kaiming");
                if (pos != std::string::npos)
                {
                    line.replace(pos, 16, "/opt/kaiming-tools/bin/kaiming");
                }

                size_t refIdPos = line.find(pmRef.ref.id);
                if (refIdPos != std::string::npos)
                {
                    if (line.find("--", refIdPos + pmRef.ref.id.length()) == std::string::npos)
                    {
                        line.insert(refIdPos + pmRef.ref.id.length(), " --");
                    }
                }
            }

            // 不存在StartupWMClass字段才新增
            if (!hasStartupWMClass)
            {
                if (i + 1 < desktopDatas.size())
                {
                    desktopDatas.insert(desktopDatas.begin() + i + 1, "StartupWMClass=" + baseName);
                    i += 2; // 跳过新增行
                }
                else
                {
                    desktopDatas.push_back("StartupWMClass=" + baseName);
                    i++;
                }
                continue;
            }
        }

        // 保留，暂不修改 Icon 字段
        if (line.find("Icon=") != std::string::npos)
        {
            size_t iconPos = line.find("=") + 1;
            std::string path = line.substr(iconPos);

            if (path.find("/usr") == 0)
            {
                path.replace(0, 4, "/opt/kaiming");
            }

            line = "Icon=" + path;
        }

        // 新增 X-Kaiming 字段，用于SDK，开始菜单等获取软件包名
        if (line.find("X-Kaiming=") != std::string::npos)
        {
            needAddKaimingTag = false;
        }
        else
        {
            needAddKaimingTag = true;
        }

        i++;
    }

    if (needAddKaimingTag)
    {
        for (auto it = desktopDatas.begin(); it != desktopDatas.end(); ++it)
        {
            if (it->find("[Desktop Entry]") != std::string::npos)
            {
                string kaimingTag = "X-Kaiming=" + pmRef.ref.id;
                desktopDatas.insert(it + 1, kaimingTag);
                break;
            }
        }
    }

    std::string bakpath = exportPath + "_bak"; 
    // 将修改后的内容写回 .desktop 文件
    if (!setDataToKVFile(bakpath, desktopDatas))
    {
        kmlogger.error("Desktop file modified failed.");
    }

    std::rename(bakpath.c_str(), exportPath.c_str());

    // fs::path userDir = KMStorageDir::getUserDirLocation();
    // size_t pos = exportDesktopFilePath.rfind('/');
    // std::string basename = exportDesktopFilePath.substr(pos + 1);
    // auto appDir = userDir / ".var" / "app" / pmRef.ref.id / "upperdir" / "usr" / "share" / "applications";

    // bool chowner = false;
    // if (! fs::exists(fs::path(userDir / ".var" / "app")))
    // {
    //     chowner = true;
    // }

    // if (!fs::exists(appDir) && !fs::create_directories(appDir))
    // {
    //     kmlogger.error ("Error creating directory: %s", appDir.c_str());
    //     return;
    // }

    // std::string appDesktop = appDir / basename;

    // if (!setDataToKVFile(appDesktop, desktopDatas))
    // {
    //     kmlogger.error("Desktop file modified failed.");
    // }

    // if (chowner)
    // {
    //     modifyDirOwnership(userDir / ".var");
    // }
    // else
    // {
    //     modifyDirOwnership(userDir / ".var" / "app" / pmRef.ref.id);
    // }

    // kmlogger.info(" destFilePath: %s", appDesktop.c_str());
    // d->m_installedFiles.insert(appDesktop);

    return;
}

bool KMPackageManager::createDesktopShortcut(const KMPMRef &pmRef, const std::string &shortcutPath)
{
    fs::path basePath = d->m_folder->getPath();
    const fs::path infoFile = basePath / "layers" / pmRef.completedRef / "info.json";

    if (!fs::exists(infoFile))
    {
        kmlogger.debug("can't find app info file: %s", infoFile.string().c_str());
        return false;
    }

    KMInfoJson infoJson;
    infoJson.loadFile(infoFile);

    if(infoJson.getAnnotations().desktops.empty()) { return false; }

    std::vector<fs::path> userDesktopDirs;
    DIR *dir = opendir("/home");
    if (dir)
    {
        struct dirent *entry;
        while ((entry = readdir(dir)) != nullptr)
        {
            if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
            {
                fs::path path = fs::path("/home") / entry->d_name / "桌面";
                if (fs::exists(path))
                {
                    userDesktopDirs.push_back(path);
                }
            }
        }
        closedir(dir);
    }

    fs::path sourceFile = shortcutPath;
    fs::path fileName = fs::path(shortcutPath).filename();

    for (const auto &userDesktop : userDesktopDirs)
    {
        fs::path userTargetFile = userDesktop / fileName;
        try
        {
            if (fs::exists(sourceFile))
            {
                fs::copy_file(sourceFile, userTargetFile, fs::copy_options::overwrite_existing);
                KMStorageDir::modifyDirOwnership(userTargetFile);
                chmod(userTargetFile.c_str(), 0755);
                d->m_installedFiles.insert(userTargetFile.string());
                kmlogger.info("Copied desktop file to user desktop: %s", userTargetFile.string().c_str());
            }
        }
        catch (const std::exception &e)
        {
            kmlogger.error("Failed to copy desktop file to user desktop: %s : %s", userTargetFile.string().c_str(), e.what());
            return false;
        }
    }

    return true;
}

bool KMPackageManager::recordDesktopMd5(const std::string &id, const std::string &desktopFilePath, std::set<std::string> &installedFiles)
{
    try
    {
        if (id.empty() || desktopFilePath.empty())
        {
            return false;
        }

        fs::path infoDir = d->m_folder->getInfoPath();
        if (!fs::exists(infoDir))
        {
            fs::create_directories(infoDir);
        }

        fs::path md5File = infoDir / (id + ".md5");
        const std::string md5 = KMFileUtils::getFileMd5sum(desktopFilePath);
        if (md5.empty())
        {
            kmlogger.warn("Failed to calc md5 for %s", desktopFilePath.c_str());
            return false;
        }

        std::ofstream ofs(md5File, std::ios::app);
        if (!ofs)
        {
            kmlogger.error("Open md5 file failed: %s", md5File.string().c_str());
            return false;
        }
        const std::string baseName = fs::path(desktopFilePath).filename().string();
        ofs << baseName << " " << md5 << "\n";
        ofs.close();

        installedFiles.insert(md5File.string());

        return true;
    }
    catch (const std::exception &e)
    {
        kmlogger.error("recordDesktopMd5 failed: %s", e.what());
        return false;
    }
}

bool KMPackageManager::removeUserDesktopShortcutsByMd5(const std::string &id)
{
    try
    {
        if (id.empty())
        {
            return false;
        }

        fs::path infoDir = d->m_folder->getInfoPath();
        fs::path md5File = infoDir / (id + ".md5");
        if (!fs::exists(md5File))
        {
            kmlogger.info("md5 record file not found for %s", id.c_str());
            return false;
        }

        std::ifstream ifs(md5File);
        if (!ifs)
        {
            kmlogger.error("Open md5 file failed: %s", md5File.string().c_str());
            return false;
        }

        // collect md5 values
        std::unordered_set<std::string> md5Set;
        std::string line;
        while (std::getline(ifs, line))
        {
            if (line.empty())
                continue;
            std::istringstream iss(line);
            std::string fname, md5;
            if (!(iss >> fname >> md5))
                continue;
            if (!md5.empty())
                md5Set.insert(md5);
        }
        ifs.close();

        if (md5Set.empty())
        {
            return false;
        }

        // scan all users' Desktop directories
        std::vector<fs::path> desktopDirs;
        DIR *dir = opendir("/home");
        if (dir)
        {
            struct dirent *entry;
            while ((entry = readdir(dir)) != nullptr)
            {
                if (entry->d_type == DT_DIR && strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
                {
                    fs::path zh = fs::path("/home") / entry->d_name / "桌面";
                    fs::path en = fs::path("/home") / entry->d_name / "Desktop";
                    if (fs::exists(zh))
                        desktopDirs.push_back(zh);
                    if (fs::exists(en))
                        desktopDirs.push_back(en);
                }
            }
            closedir(dir);
        }

        for (const auto &desk : desktopDirs)
        {
            for (const auto &entry : fs::directory_iterator(desk))
            {
                if (!entry.is_regular_file())
                    continue;
                const auto &p = entry.path();
                if (p.extension() != ".desktop")
                    continue;

                std::string curMd5 = KMFileUtils::getFileMd5sum(p.string());
                if (!curMd5.empty() && md5Set.find(curMd5) != md5Set.end())
                {
                    std::error_code ec;
                    fs::remove(p, ec);
                    if (ec)
                    {
                        kmlogger.warn("Failed to remove desktop file: %s (%s)", p.string().c_str(), ec.message().c_str());
                    }
                    else
                    {
                        kmlogger.info("Removed desktop shortcut: %s", p.string().c_str());
                    }
                }
            }
        }
        return true;
    }
    catch (const std::exception &e)
    {
        kmlogger.error("removeUserDesktopShortcutsByMd5 failed: %s", e.what());
        return false;
    }
}

bool KMPackageManager::createExportBinShellScript(KMPMRef pmRef, string fileName)
{
    // 设置内容
    string shellHead = "#!/bin/sh";
    string content = shellHead.append("\nexec ").append("/opt/kaiming-tools/bin/kaiming run --branch=").append(pmRef.ref.channel).append(" --arch=").append(pmRef.ref.arch).append(" ").append(pmRef.ref.id).append(" \"$@\"\n");

    kmlogger.info("export bin bash content:\n%s", content.c_str());
    // 创建文件并写入内容
    std::ofstream file(fileName);
    if (file.is_open())
    {
        file << content;
        file.close();
    }
    else
    {
        kmlogger.error("Failed to open file:  %s", fileName.c_str());
        return false;
    }

    // 设置文件权限为 0755
    if (chmod(fileName.c_str(), 0755) != 0)
    {
        kmlogger.error("Failed to set file permission for:  %s", fileName.c_str());
        return false;
    }

    return true;
}

bool KMPackageManager::createInstalledFile(string fileName, bool append)
{
    // 设置内容
    string content;

    for (auto &installedFile : d->m_installedFiles)
    {
        content = content.append(installedFile).append("\n");
    }

    // 创建文件并写入内容
    std::ofstream file;
    if (append)
    {
        file.open(fileName, std::ios::app);  // 追加模式
    }
    else
    {
        if (fs::exists(fileName))
        {
            fs::remove(fileName);
        }
        file.open(fileName, std::ios::out);  // 覆盖模式（默认）
    }

    if (file.is_open())
    {
        file << content;
        file.close();
    }
    else
    {
        kmlogger.error("Failed to open file:  %s", fileName.c_str());
        return false;
    }

    // 设置文件权限为 0755
    if (chmod(fileName.c_str(), 0755) != 0)
    {
        kmlogger.error("Failed to set file permission for:  %s", fileName.c_str());
        return false;
    }

    return true;
}

void KMPackageManager::writeInstalledFilesToList(const std::string &filePath)
{
    fs::path dirPath = fs::path(filePath).parent_path();

    if (!fs::exists(dirPath))
    {
        if (!fs::create_directories(dirPath))
        {
            KMError("Error creating directory: " + dirPath.string());
            return;
        }
    }

    std::ofstream outFile(filePath);

    if (!outFile)
    {
        KMError("Error opening file: " + filePath);
        return;
    }

    for (const auto &installedFile : d->m_installedFiles)
    {
        outFile << installedFile << "\n";
    }

    outFile.close();
}

void KMPackageManager::modifyExportsDirectory(KMPMRef &pmRef, const std::string &srcDir, const std::string &destDir)
{
    for (const auto &entry : fs::directory_iterator(srcDir))
    {
        if (fs::is_directory(entry))
        {
            // 递归处理子目录
            std::string subSrcDir = entry.path().string();
            std::string subDestDir = destDir + "/" + entry.path().filename().string();

            string removeStr = "/usr";
            size_t pos = subDestDir.find(removeStr);

            if (pos != std::string::npos)
            {
                subDestDir.erase(pos, removeStr.length());
            }

            if (subSrcDir.find("entries/share/kylin-user-guide/data/guide/") != std::string::npos)
            {
                size_t pos = subSrcDir.rfind('/');
                std::string basename = subSrcDir.substr(pos + 1);
                std::string dataDestPath = "/opt/system/resource/kylin/kylin-user-guide/data/guide/" + basename;
                handleSpecialFileInstall(subSrcDir, dataDestPath, true);
                continue;
            }

            fs::create_directory(subDestDir);
            modifyExportsDirectory(pmRef, subSrcDir, subDestDir);
        }
        else
        {
            // 处理文件
            std::string srcFilePath = entry.path().string();
            std::string destFilePath = destDir + "/" + entry.path().filename().string();
            kmlogger.debug("srcFilePath:%s destFilePath:%s", srcFilePath.c_str(), destFilePath.c_str());

            string removeStr = "/usr";
            size_t pos = destFilePath.find(removeStr);
            if (pos != std::string::npos)
            {
                destFilePath.erase(pos, removeStr.length());
            }
            kmlogger.debug("srcFilePath:%s destFilePath:%s", srcFilePath.c_str(), destFilePath.c_str());

            if (fs::exists(fs::path(destFilePath)) && fs::is_symlink(fs::path(destFilePath)))
            {
                kmlogger.info("destFilePath  %s exists.", destFilePath.c_str());
                d->m_installedFiles.insert(destFilePath);
                continue;
            }

            if (srcFilePath.find("entries/share/pixmaps/") != std::string::npos)
            {
                string destDir = "/opt/kaiming/share/icons/hicolor/32x32/apps/";
                string destDir2 = "/opt/kaiming/share/icons/hicolor/scalable/apps/";
                size_t pos = srcFilePath.find("entries/share/pixmaps/");
                std::string basename = srcFilePath.substr(pos + 22);
                std::string destPath = destDir + basename;
                std::string destPath2 = destDir2 + basename;
                fs::path p(destPath);
                fs::path parent_path = p.parent_path();
                fs::path p2(destPath2);
                fs::path parent_path2 = p2.parent_path();
                std::string dataDestPath = parent_path.string();
                std::string dataDestPath2 = parent_path2.string();
                handleSpecialFileInstall(srcFilePath, dataDestPath, false);
                handleSpecialFileInstall(srcFilePath, dataDestPath2, false);
            }
            else if (srcFilePath.find(".desktop") != std::string::npos || srcFilePath.find(".service") != std::string::npos || srcFilePath.find(".svg") != std::string::npos || srcFilePath.find(".png") != std::string::npos || srcFilePath.find(".xpm") != std::string::npos)
            {

                // 如果是 .desktop, .service, .svg 文件，则创建相对路径软链接到目标目录
                // 此处以 ".desktop" 为后缀，否则会出现 "org.freedesktop.impl.portal.desktop.gtk.service" 也会进行修改。

                if (srcFilePath.find("entries/etc/xdg/autostart") != std::string::npos)
                {
                    // fs::path userDir = KMStorageDir::getUserDirLocation();
                    // fs::path destXdgPath = userDir / ".config" / "autostart";
                    fs::path destXdgPath = "/etc/xdg/autostart";
                    fs::path destFile = destXdgPath / fs::path(srcFilePath).filename();

                    if (KMStringUtils::endsWith(srcFilePath, ".desktop"))
                    {
                        modifyDesktopFile(pmRef, srcFilePath, destFile);
                        kmlogger.info("autostart .desktop srcPath:  %s destFilePath: %s", srcFilePath.c_str(), destFilePath.c_str());
                        d->m_installedFiles.insert(destFile.string());
                    }
                }
                else
                {
                    if (KMStringUtils::endsWith(srcFilePath, ".desktop"))
                    {
                        modifyDesktopFile(pmRef, srcFilePath, destFilePath);
                        recordDesktopMd5(pmRef.ref.id, destFilePath, d->m_installedFiles);
                        createDesktopShortcut(pmRef, destFilePath);
                        kmlogger.info(".desktop srcPath: %s destFilePath: %s", srcFilePath.c_str(), destFilePath.c_str());

                        // 在 /opt/kaiming/share/idtodesktop 文件中记录映射关系
                        std::string idToDesktopFile = "/opt/kaiming/share/idtodesktop";
                        std::vector<std::string> idToDesktopFileDatas = getDataFromKVFile(idToDesktopFile);
                        size_t lastSlashPos = srcFilePath.find_last_of("/\\");
                        std::string desktopFileName = (lastSlashPos == std::string::npos) ? srcFilePath : srcFilePath.substr(lastSlashPos + 1);
                        std::string idDesktop = pmRef.ref.id + '=';
                        bool hasId = false;

                        for (auto data : idToDesktopFileDatas)
                        {
                            if (data.find(idDesktop) != std::string::npos)
                            {
                                data = idDesktop + desktopFileName;
                                hasId = true;
                                break;
                            }
                        }

                        if (!hasId)
                        {
                            idToDesktopFileDatas.push_back(idDesktop + desktopFileName);
                        }

                        setDataToKVFile(idToDesktopFile, idToDesktopFileDatas);
                        d->m_installedFiles.insert(destFilePath);
                        continue;
                    }

                    // 获取 srcFilePath 相对于 destFilePath 的相对路径
                    std::string relativePath = fs::relative(fs::path(srcFilePath), fs::path(destFilePath).parent_path()).string();
                    kmlogger.info("Export .desktop, .service, .svg, .png relativePath:  %s destFilePath: %s", relativePath.c_str(), destFilePath.c_str());

                    if (fs::is_symlink(fs::path(destFilePath)) || fs::exists(fs::path(destFilePath)))
                    {
                        // 如果存在，删除该文件或链接
                        kmlogger.info("destFilePath  %s exists. delete it.", destFilePath.c_str());
                        fs::remove(fs::path(destFilePath));
                    }

                    fs::create_symlink(fs::path(relativePath), fs::path(destFilePath));
                    d->m_installedFiles.insert(destFilePath);
                }
            }
            else if (srcFilePath.find("entries/usr/bin") != std::string::npos || srcFilePath.find("entries/bin") != std::string::npos)
            {
                // 如果是 entries/bin 二进制文件，则创建相对路径软链接到目标目录
                std::string relativePath = fs::relative(fs::path(srcFilePath), fs::path(destFilePath).parent_path()).string();
                kmlogger.info("Export bin relativePath:  %s destFilePath: %s", relativePath.c_str(), destFilePath.c_str());

                // 使用 fs::exists 检测软链接的存在，它会返回目标文件的存在状态，而不是软链接本身。因此，使用 fs::is_symlink 是判断软链接是否存在的正确方法。
                if (fs::is_symlink(fs::path(destFilePath)))
                {
                    // 如果存在，删除该文件或链接
                    kmlogger.info("destFilePath  %s exists. delete it.", destFilePath.c_str());
                    fs::remove(fs::path(destFilePath));
                }

                fs::create_symlink(fs::path(relativePath), fs::path(destFilePath));
                d->m_installedFiles.insert(destFilePath);
            }
            else if (srcFilePath.find(".xml") != std::string::npos)
            {
                std::string resourceDir = "/opt/system/resource/mime/packages";
                handleSpecialFileInstall(srcFilePath, resourceDir, false);
            }
            else if (srcFilePath.find(".policy") != std::string::npos)
            {
                string destDir = KMFileUtils::isImmutableSystem() ? "/opt/system/resource/polkit-1/actions" : "/usr/share/polkit-1/actions";
                handleSpecialFileInstall(srcFilePath, destDir, false);
            }
            else if (srcFilePath.find("entries/home/") != std::string::npos)
            {
                fs::path userDir = KMStorageDir::getUserDirLocation();
                size_t pos = srcFilePath.find("entries/home/");
                std::string relativePath = srcFilePath.substr(pos + strlen("entries/home/"));
                fs::path destPath = userDir / relativePath;
                fs::path destDirPath = destPath.parent_path();

                if (!fs::exists(destDirPath))
                {
                    fs::create_directories(destDirPath);
                    kmlogger.info("Created user home directory: %s", destDirPath.string().c_str());
                }

                if (fs::is_directory(srcFilePath))
                {
                    handleSpecialFileInstall(srcFilePath, destPath.string(), true);
                }
                else
                {
                    handleSpecialFileInstall(srcFilePath, destDirPath.string(), false);
                }

                continue;
            }
            else if (srcFilePath.find("entries/assets/") != std::string::npos)
            {
                size_t pos = srcFilePath.find("entries/assets/");
                std::string basename = srcFilePath.substr(pos + 15);
                std::string destPath = "/" + basename;
                fs::path p(destPath);
                fs::path parent_path = p.parent_path();
                std::string dataDestPath = parent_path.string();
                handleSpecialFileInstall(srcFilePath, dataDestPath, false);
                KMStorageDir::modifyDirOwnership(dataDestPath);
                continue;
            }
        }
    }
}

bool KMPackageManager::handleSpecialFileInstall(const std::string &srcFilePath, const std::string &destDir, bool isDir)
{
    try
    {
        // 1. 确保目标目录存在
        if (!fs::exists(destDir))
        {
            fs::create_directories(destDir);
            kmlogger.info("Created resource directory: %s", destDir.c_str());
        }

        // 2. 构造目标路径
        fs::path srcPath(srcFilePath);
        fs::path destDirPath(destDir);
        fs::path destPath = destDirPath / srcPath.filename();

        if (isDir)
        {
            fs::copy(srcPath, destDirPath, fs::copy_options::recursive | fs::copy_options::overwrite_existing);
            d->m_installedFiles.insert(destDir);
            return true;
        }

        kmlogger.info("Copying file from %s to %s", srcFilePath.c_str(), destPath.string().c_str());

        // 3. 检查并删除已存在的目标文件/链接
        if (fs::exists(destPath))
        {
            fs::remove(destPath);
            kmlogger.info("Removed existing file/link: %s", destPath.string().c_str());
        }

        // 4. 执行文件拷贝
        fs::copy_file(srcPath, destPath, fs::copy_options::overwrite_existing);

        kmlogger.info("Successfully copied file to %s", destPath.string().c_str());

        // 5. 添加到已安装文件集合
        d->m_installedFiles.insert(destPath.string());

        return true;
    }
    catch (const fs::filesystem_error &e)
    {
        kmlogger.error("Failed to process file %s: %s", srcFilePath.c_str(), e.what());
        return false;
    }
}

void KMPackageManager::runMultiperTriggerUpdateCacheCommand(const vector<string> &cacheShellPaths)
{
    for (const auto &path : cacheShellPaths)
    {
        runTriggerUpdateCacheCommand(path);
    }
}

void KMPackageManager::runTriggerUpdateCacheCommand(const std::string &cacheShellPath)
{
    // 构建命令字符串，将脚本路径和参数拼接在一起
    std::string command = cacheShellPath + " " + "/opt/kaiming";

    kmlogger.info("Generate cache command: %s", command.c_str());

    // 执行命令
    int result = std::system(command.c_str());
    if (result != 0)
    {
        kmlogger.error("Failed to execute command:  %s", command.c_str());
    }
}

// 线程函数：实时读取rsync的输出并解析进度信息
void KMPackageManager::monitorProgress(FILE *pipe)
{
    char buffer[256];
    while (fgets(buffer, sizeof(buffer), pipe) != nullptr)
    {
        std::string line(buffer);
        // 查找包含百分比的行，表示文件传输的进度
        size_t firstPos = line.find('=');
        if (firstPos != std::string::npos)
        {
            size_t secondPos = line.find(')', firstPos + 1);
            // 提取进度百分比
            std::string progresStr = line.substr(firstPos, secondPos); // 获取进度
            size_t thirdPos = progresStr.find('/');
            std::string numBeforeStr = progresStr.substr(1, thirdPos - 1);
            int numBefore, numAfter;
            std::stringstream(numBeforeStr) >> numBefore;
            std::string numAfterStr = progresStr.substr(thirdPos + 1, progresStr.length() - thirdPos - 3);
            std::stringstream(numAfterStr) >> numAfter;
            int result = (numAfter - numBefore);
            int divid = (int)((double)result / numAfter * 100);
            sharedValue.store(divid, std::memory_order_relaxed); // 在线程中修改共享变量的值
        }
    }
}

std::string KMPackageManager::getCertificateOuname(KMLibHandle& lib) 
{
    try 
    {
        const std::string configPath = "/etc/dpkg/dpkg.cfg";
        
        if (!KMFileUtils::fileExists(configPath)) 
        {
            kmlogger.info("Config file not found: %s", configPath.c_str());
            return "";
        }

        using GetProfileStringFunc = int(*)(const char*, const char*, char*);
        auto GetProfileString = lib.loadSymbol<GetProfileStringFunc>("GetProfileString");
        if (!GetProfileString) return "";

        char ouname[1024] = {0};
        if (GetProfileString(configPath.c_str(), "ou", ouname) != 0) 
        {
            kmlogger.info("Failed to get OU from config file");
            return "";
        }
        
        kmlogger.info("Got OU name: %s", ouname);
        return std::string(ouname);
    } 
    catch (...) 
    {
        kmlogger.error("getCertificateOuname failed");
        return "";
    }
}

std::string KMPackageManager::getPemCN(KMLibHandle& lib, const std::string& pemFile) 
{
    try 
    {
        using GetPemSubCNFunc = int(*)(const char*, char*);
        auto GetPemSubCN = lib.loadSymbol<GetPemSubCNFunc>("getPemSubCN");
        if (!GetPemSubCN) return "";

        char subjectCN[256] = {0};
        if (GetPemSubCN(pemFile.c_str(), subjectCN) != 0)
        {
            kmlogger.info("Failed to get CN");
            return "";
        }
        return std::string(subjectCN);
    } 
    catch (...) 
    {
        kmlogger.error("getPemCN failed");
        return "";
    }
}

bool KMPackageManager::isV10Sp1()
{
    std::ifstream file("/etc/os-release");
    
    bool isV10Sp1 = false;
    if (file.is_open())
    {
        std::string line;
        while (std::getline(file, line))
        {
            if (KMStringUtils::startsWith(line, "PRETTY_NAME=") && KMStringUtils::contains(line, "Kylin V10 SP1"))
            {
                isV10Sp1 = true;
                kmlogger.info("The system is V10");
                break;
            }
        }
    }

    return isV10Sp1;
}

int KMPackageManager::verifySignature(std::string id, std::string kind, fs::path path) 
{
    // base,runtime类型不验签，v10sp1不验签
    if (kind == "base" || kind == "runtime" || isV10Sp1()) 
    {
        kmlogger.info("base,runtime类型不验签, v10sp1不验签, 直接部署");
        return KM_ERROR_NO;
    }

    KMLibHandle libSign(nullptr);
    try
    {
        libSign = KMLibHandle("libkylin_signtool.so.0.0.0");
    }
    catch(...)
    {
        kmlogger.error("Skip signature verification");
        return KM_ERROR_NO;
    }
    
    int safeStatus = getSafeMode(libSign);
    kmlogger.info("Safe mode is: %d", safeStatus);

    if (safeStatus <= 1) 
    {
        kmlogger.info("安全模式为关闭模式或获取安全模式失败，跳过验签");
        return KM_ERROR_NO;
    }

    // 签名工具不存在，跳过验签
    if (!isKylinFileSignToolPresent()) 
    {
        kmlogger.info("签名工具不存在，跳过验签");
        return KM_ERROR_NO;
    }

    // 签名文件检查
    std::string sigFilesPath = (path / "sig").string();
    std::string filesMd5 = KMStringUtils::buildFilename(path, "files.md5");
    std::string filesSign = KMStringUtils::buildFilename(sigFilesPath, "files.sig");
    std::string filesPem = KMStringUtils::buildFilename(sigFilesPath, "files.pem");

    if (!KMFileUtils::fileExists(filesMd5))
    {
        kmlogger.info("签名文件不存在，停止安装");
        std::cout << _("Signature file not exist, installation stopped") << std::endl;
        return KM_ERROR_NO_MD5_FILES;
    }

    if (!KMFileUtils::fileExists(filesSign) || !KMFileUtils::fileExists(filesPem)) 
    {
        kmlogger.info("files.sig or files.pem not exist");
        std::cout << _("Signature verification failed") << std::endl;
        int errorCode = resolveFailedVerification(safeStatus, path, id);
        return errorCode;
    }

    // 证书验证
    if (!verifyCertificate(libSign, filesPem)) 
    {
        // 证书验证失败
        kmlogger.info("证书验证失败");
        std::cout << _("Signature verification failed") << std::endl;
        int errorCode = resolveFailedVerification(safeStatus, path, id);
        return errorCode;
    }

    // 命令行验签
    int verifyResult = executeSignatureVerification(filesMd5, filesSign, filesPem);
    if (verifyResult != KM_ERROR_NO) 
    {
        kmlogger.info("命令行验签失败");
        std::cout << _("Signature verification failed") << std::endl;
        int errorCode = resolveFailedVerification(safeStatus, path, id);
        return errorCode;
    }

    kmlogger.info("命令行验签成功");
    std::cout << _("Signature verification success") << std::endl;
    // MD5校验
    if (!KMFileUtils::isObsolete(filesMd5)) 
    {
        kmlogger.info("MD5 file is not old");
        KMDirMd5sum md5sum(path);
        if (!md5sum.checksum("files")) 
        {
            kmlogger.info("cheksum MD5 files, the result is KM_ERROR_MD5_CHECK_FAILED");
            return KM_ERROR_MD5_CHECK_FAILED;
        }
    }

    kmlogger.info("Signature verification completed successfully");
    return KM_ERROR_NO;

}

bool KMPackageManager::verifyCertificate(KMLibHandle& lib, const std::string& pemFile) 
{
    try 
    {
        const std::string configPath = "/etc/dpkg/dpkg.cfg";
        
        if (!KMFileUtils::fileExists(configPath)) 
        {
            kmlogger.info("Config file not found: %s", configPath.c_str());
            return false;
        }

        using GetProfileStringFunc = int (*)(const char*, const char*, char*);
        using GetPemSubCNFunc = int (*)(const char*, char*);
        
        auto GetProfileString = lib.loadSymbol<GetProfileStringFunc>("GetProfileString");
        auto GetPemSubCN = lib.loadSymbol<GetPemSubCNFunc>("getPemSubCN");
        
        if (!GetProfileString || !GetPemSubCN) 
        {
            kmlogger.info("Failed to load required symbols, skip certificate verification");
            return true;
        }

        char ouBuffer[1024] = {0};
        if (GetProfileString("/etc/dpkg/dpkg.cfg", "ou", ouBuffer) != 0) 
        {
            kmlogger.info("Failed to get OU name, skip certificate verification");
            return true;
        }
        std::string ouname(ouBuffer);
        kmlogger.info("Got OU name: %s", ouname.c_str());

        if (ouname.empty()) 
        {
            kmlogger.info("OU name is empty, skip certificate verification");
            return true;
        }

        char cnBuffer[256] = {0};
        if (GetPemSubCN(pemFile.c_str(), cnBuffer) != 0) 
        {
            kmlogger.info("Failed to get CN");
            return false;
        }
        std::string cn(cnBuffer);
        kmlogger.info("Got CN: %s", cn.c_str());

        if (!verifyCertCN(ouname, cn)) 
        {
            kmlogger.info("OU-CN mismatch (OU is : %s, CN is : %s)", ouname.c_str(), cn.c_str());
            return false;
        }

        kmlogger.info("Certificate verified (OU is : %s, CN is : %s)", ouname.c_str(), cn.c_str());
        return true;
    } 
    catch (...) 
    {
        return false;
    }
}

int KMPackageManager::executeSignatureVerification(const std::string& md5File, const std::string& sigFile, const std::string& pemFile) 
{
    std::string command = "kylinfilesigntool -v \"" + md5File + "\" -s \"" + sigFile + "\" -c \"" + pemFile + "\" >/dev/null 2>&1";
    try 
    {
        kmlogger.info("Executing: %s", command.c_str());
        int ret = std::system(command.c_str());
        if (ret != 0) 
        {
            kmlogger.info("Signature verification failed (exit code: %d)", ret);
            return KM_ERROR_SIGN_FAILED;
        }
        return KM_ERROR_NO;
    }
    catch (...) 
    {
        kmlogger.info("Unexpected error during signature verification");
        return KM_ERROR_SIGN_FAILED;
    }
}

std::string KMPackageManager::trim(const std::string& str) 
{
    size_t start = str.find_first_not_of(" \t\n\r");
    if (start == std::string::npos) return "";
    size_t end = str.find_last_not_of(" \t\n\r");
    return str.substr(start, end - start + 1);
}

std::vector<std::string> KMPackageManager::splitString(const std::string& str, char delimiter) 
{
    std::vector<std::string> tokens;
    size_t start = 0, end;
    
    while ((end = str.find(delimiter, start)) != std::string::npos) 
    {
        // 分割子串，并去除前后空格
        std::string token = str.substr(start, end - start);
        token = trim(token);
        tokens.push_back(token);
        start = end + 1;
    }
    
    // 处理最后一个子串（可能没有分隔符的情况）
    std::string lastToken = str.substr(start);
    lastToken = trim(lastToken);
    tokens.push_back(lastToken);
    
    return tokens;
}

bool KMPackageManager::verifyCertCN(const std::string& ouname, const std::string& certCN) 
{
    // 分割 OU 列表（如 "OU1,OU2" -> ["OU1", "OU2"]）
    std::vector<std::string> allowedOUs = splitString(ouname, ',');

    // 检查 CN 是否在 OU 列表中
    bool isValid = std::find(allowedOUs.begin(), allowedOUs.end(), certCN) != allowedOUs.end();
    if (!isValid) 
    {
        kmlogger.error("CN verification failed: %s (allowed OUs: %s)", certCN.c_str(), ouname.c_str());
    }
    else 
    {
        kmlogger.info("CN verification success: %s", certCN.c_str());
    }

    return isValid;
}

// 判断签名工具是否存在
bool KMPackageManager::isKylinFileSignToolPresent()
{
    int result = std::system("which kylinfilesigntool > /dev/null 2>&1");
    // 结果为0，找到工具
    return (result == 0);
}

KMErrorCodeEnum KMPackageManager::setKsafLabelAndExectl(const std::set<std::string> &files, const std::string &appName, const std::string &kind, const std::string &path)
{
    if (files.empty() || appName.empty())
    {
        kmlogger.info("Invalid parameters: files or appName is empty");
        return KM_ERROR_INVALID_PARAM;
    }

    try
    {
        KMLibHandle ksafLabelHandle("libksaflabelmgr.so");
        KMLibHandle exectlHandle("libkysec2_exectl_wlist.so.0.0.0");
        if (!ksafLabelHandle || !exectlHandle)
        {
            kmlogger.info("Failed to load required libraries");
            return KM_ERROR_SETLABEL_FAILED;
        }

        using SetLabelFunc = int (*)(const char **, const char *);
        using XattrSetFunc = int (*)(char *[], size_t);
        using SetLabelForInterpreterFunc = int (*)(const char *);

        std::vector<const char *> c_files;
        std::vector<char *> c_paths;
        c_files.reserve(files.size() + 1);
        c_paths.reserve(files.size());
        for (const auto &file : files)
        {
            c_files.push_back(file.c_str());
            c_paths.push_back(const_cast<char *>(file.c_str()));
        }
        c_files.push_back(nullptr); // 以nullptr结尾

        if ((kind == "base" || kind == "runtime") && !d->m_isHostapp)
        {
            // base/runtime只设置解释器的ksaf标记
            kmlogger.info("setLabelForKaimingInterpreter for base or runtime");
            auto setLabelForKaimingInterpreter = ksafLabelHandle.loadSymbol<SetLabelForInterpreterFunc>("setLabelForKaimingInterpreter");

            if (int ret = setLabelForKaimingInterpreter(path.c_str()); ret != 0)
            {
                kmlogger.error("Failed to 'setLabelForKaimingInterpreter': %d, path: %s", ret, path.c_str());
                return KM_ERROR_SETLABEL_FAILED;
            }
        }
        else
        {
            auto setLabelForKaiming = ksafLabelHandle.loadSymbol<SetLabelFunc>("setLabelForKaiming");

            if (int ret = setLabelForKaiming(c_files.data(), appName.c_str()); ret != 0)
            {
                kmlogger.error("Failed to 'setLabelForKaiming' (code: %d)", ret);
                return KM_ERROR_SETLABEL_FAILED;
            }
        }

        kmlogger.info("set label successfully");

        if (kind == "app" || d->m_isHostapp)
        {
            // exectl only set app
            auto exectl_xattr_multi_set = exectlHandle.loadSymbol<XattrSetFunc>("exectl_wlist_multi_add");

            int ret = exectl_xattr_multi_set(c_paths.data(), c_paths.size());
            if (ret < 0)
            {
                kmlogger.error("Failed to set xattr (code: %d)", ret);
                return KM_ERROR_SETLABEL_FAILED;
            }

            kmlogger.info("set exectl xattr successfully (code: %d)", ret);
        }
    }
    catch (...)
    {
        kmlogger.error("setKsafLabelAndExectl crashed unexpectedly");
        return KM_ERROR_SETLABEL_FAILED;
    }

    kmlogger.info("setKsafLabelAndExectl completed successfully");
    return KM_ERROR_NO;
}

int KMPackageManager::getSafeMode(KMLibHandle& lib) 
{
    try 
    {
        using GetDpkgInfoFunc = int(*)();
        auto GetDpkgInfo = lib.loadSymbol<GetDpkgInfoFunc>("get_dpkg_file_info");
        if (!GetDpkgInfo) return 0;
        return GetDpkgInfo();
    } 
    catch (...) 
    {
        kmlogger.error("getSafeMode failed");
        return 0;
    }
}

int KMPackageManager::resolveFailedVerification(int safeStatus, fs::path idPath, std::string id)
{
    switch (safeStatus)
    {
    case 1:
        kmlogger.info("安全模式为关闭模式，跳过验签");
        return KM_ERROR_NO;

    case 2:
    {
        void *handle = dlopen("libkysec.so.0.0.0", RTLD_LAZY);
        if (!handle)
        {
            kmlogger.info("Failed to load libkysec.so.0.0.0: %s", dlerror());
            return KM_ERROR_SIGN_FAILED;
        }

        dlerror();

        using SignCheckFunc = int (*)(const char *, const char *);
        SignCheckFunc kysec_check_custom_pkg_sign = (SignCheckFunc)dlsym(handle, "kysec_check_custom_pkg_sign");

        const char *dlsym_error = dlerror();
        if (dlsym_error)
        {
            kmlogger.info("Failed to find kysec_check_pkg_sign: %s", dlsym_error);
            dlclose(handle);
            return KM_ERROR_SIGN_FAILED;
        }

        // 返回值 1:允许安装;0:禁止安装
        int signStatus = kysec_check_custom_pkg_sign(const_cast<char *>(id.c_str()), const_cast<char *>(idPath.c_str()));
        kmlogger.info("User selection after popup: %s", signStatus ? "允许安装" : "禁止安装");

        dlclose(handle);
        return signStatus == 1 ? KM_ERROR_NO : KM_ERROR_USER_ABORTED;
    }

    case 3:
        kmlogger.error("安全模式为阻止模式，验签失败，拒绝安装");
        return KM_ERROR_SIGN_FAILED;

    default:
        kmlogger.error("获取安全模式失败");
        return KM_ERROR_GET_SAFE_MODE_FAILED;
    }
}

int KMPackageManager::pullFromOstree(fs::path path, KMPMRef downloadRef)
{
    fs::path tmpPath = path;
    kmlogger.info("Begin to deploy temporary files to: %s", tmpPath.string().c_str());

    // d->m_installedFiles.clear();
    kmlogger.info("completedRef: %s", downloadRef.completedRef.c_str());

    fs::path idPath = tmpPath / downloadRef.ref.id;
    kmlogger.debug("idPath: %s", idPath.string().c_str());

    // d->m_installedFiles.insert(idPath.string());

    if (std::filesystem::exists(idPath) || std::filesystem::create_directories(idPath))
    {
        kmlogger.debug("Directory created or already exists successfully!");
        fs::remove_all(idPath);
    }

    kmlogger.debug("Begin to checkout ...");
    string latestCommit = d->m_ostreeHandler->readLatestCommit(downloadRef.completedRef);
    // 生成files.md5等文件,从 OSTree 仓库中检出（checkout）指定的提交（commit），并将内容部署到指定的路径
    d->m_ostreeHandler->checkout(latestCommit, idPath.string());
    kmlogger.debug("End to checkout.");
    kmlogger.info("End to deploy files.");

    return 0;
}

string KMPackageManager::getRemoteUrl(const string &remoteName)
{
    return d->m_ostreeHandler->getRemoteUrl(remoteName);
}

bool KMPackageManager::clearCacheFiles(const string &id)
{
    const fs::path infoPath = d->m_folder->getInfoPath();
    const fs::path infoListFile = infoPath / (id + ".list");
    const fs::path binListFile = infoPath / (id + ".bin");

    std::error_code ec;
    bool allRemoved = true;

    auto removeFile = [&allRemoved](const fs::path &file)
    {
        std::error_code ec;
        if (!fs::remove(file, ec))
        {
            if (ec.value() != static_cast<int>(std::errc::no_such_file_or_directory))
            {
                kmlogger.debug("Failed to remove %s: %s", file.string().c_str(), ec.message().c_str());
                allRemoved = false;
            }
        }
        return !ec;
    };

    removeFile(infoListFile);
    removeFile(binListFile);

    return allRemoved;
}

bool KMPackageManager::removeHostAppDeployFiles(const std::string &strPath, TaskType type)
{
    std::string packageId = KMStringUtils::extractPackageId(strPath);
    if (!packageId.empty())
    {
        d->m_hostAppDeploy->setHostAppConfig(strPath, packageId);
        if (d->m_hostAppDeploy->loadHostAppInfo())
        {
            d->m_hostAppDeploy->uninstall(type);
        }

        clearCacheFiles(packageId);
    }

    return true;
}

void KMPackageManager::removeHardlinksInPlace(const fs::path &dir)
{
    try
    {
        std::unordered_set<ino_t> processed_inodes;

        for (const auto &entry : fs::recursive_directory_iterator(dir))
        {
            if (fs::is_regular_file(entry))
            {
                // 正确获取 inode 的方式
                struct stat file_stat;
                if (stat(entry.path().c_str(), &file_stat) == 0)
                {
                    ino_t inode = file_stat.st_ino;

                    if (processed_inodes.find(inode) == processed_inodes.end())
                    {
                        processed_inodes.insert(inode);
                    }
                    else
                    {
                        // 处理硬链接：创建临时副本
                        fs::path temp_file = entry.path().string() + ".tmp";

                        // 复制内容
                        std::ifstream src(entry.path(), std::ios::binary);
                        std::ofstream dst(temp_file, std::ios::binary);
                        dst << src.rdbuf();
                        src.close();
                        dst.close();

                        // 替换原文件
                        fs::rename(temp_file, entry.path());
                    }
                }
            }
        }
    }
    catch (const fs::filesystem_error &e)
    {
        std::cerr << "Error: " << e.what() << std::endl;
    }
}

void KMPackageManager::processServiceFiles(const fs::path &sourceDir, const std::string &destDir, KMPMRef &downloadRef, std::set<std::string> &installedFiles)
{
    if (!fs::exists(sourceDir))
        return;

    std::vector<std::string> files;
    if (!getAllFilesInDirectory(sourceDir, files))
        return;

    auto serviceNames = getServiceName(files);
    for (const auto &serviceName : serviceNames)
    {
        size_t lastSlashPos = serviceName.find_last_of('/');
        if (lastSlashPos != std::string::npos)
        {
            // 检查是否为无效软链接
            if (fs::is_symlink(serviceName) && !fs::exists(serviceName))
            {
                continue; // 跳过无效软链接
            }
            std::string filename = serviceName.substr(lastSlashPos + 1);
            std::string destPath = destDir + filename;
            modifyAppServiceFile(downloadRef, serviceName, destPath);
            installedFiles.insert(destPath);
        }
    }
}

void KMPackageManager::startTargetWantsServices(const fs::path &sourceDir)
{
    // check and start services
    const fs::path serviceDir = sourceDir / "entries" / "etc" / "systemd" / "system" / "multi-user.target.wants";
    if (fs::exists(serviceDir))
    {
        for (const auto &entry : fs::directory_iterator(serviceDir))
        {
            if (entry.path().extension() == ".service")
            {
                int reloadResult = system("systemctl daemon-reload");
                if (reloadResult == 0)
                {
                    std::string serviceName = entry.path().stem().string();
                    std::string cmd = "systemctl enable --now " + serviceName;
                    int result = system(cmd.c_str());
                    if (result == 0)
                    {
                        kmlogger.info("Service %s started successfully", serviceName.c_str());
                    }
                    else
                    {
                        kmlogger.error("Failed to start service %s", serviceName.c_str());
                    }
                }
                else
                {
                    kmlogger.error("Failed to reload systemd daemon, exit code: %s", std::to_string(reloadResult).c_str());
                }
            }
        }
    }
}

void KMPackageManager::modifyBaseDir(std::string baseDir)
{
    // 需要检查的文件/目录列表
    const std::vector<std::string> relPaths = {
        "/files/usr/bin/sudo",
        "/files/etc/sudoers",
        "/files/usr/lib/sudo",
        "/files/usr/libexec/sudo"};

    for (const auto &relPath : relPaths)
    {
        struct stat fileStat;
        fs::path target = fs::path(baseDir + relPath);
        // 检查文件/目录是否存在
        if (stat(target.c_str(), &fileStat) == 0)
        {
            // 修改所有者（需要root权限）
            if (chown(target.c_str(), 0, 0) == 0)
            {
                kmlogger.info("Successfully changed owner to root :%s", target.c_str());
            }
        }
    }
}

bool KMPackageManager::copyDirectory(const fs::path& source, const fs::path& destination)
{
    try {
        if (!fs::exists(source))
        {
            std::cerr << "源目录不存在: " << source << std::endl;
            return false;
        }

        if (!fs::is_directory(source))
        {
            std::cerr << "源路径不是目录: " << source << std::endl;
            return false;
        }

        // 创建目标目录
        fs::create_directories(destination);

        // 使用 directory_iterator 而不是 recursive_directory_iterator
        // 手动处理递归，以便更好地控制错误
        for (const auto& entry : fs::directory_iterator(source))
        {
            fs::path targetPath = destination / entry.path().filename();

            if (fs::is_directory(entry.status()))
            {
                // 递归复制子目录
                if (!copyDirectory(entry.path(), targetPath))
                {
                    return false;
                }
            }
            else if (fs::is_regular_file(entry.status()))
            {
                try
                {
                    fs::copy_file(entry.path(), targetPath, fs::copy_options::overwrite_existing);
                }
                catch (const fs::filesystem_error& e)
                {
                    std::cerr << "复制文件失败: " << e.what() << std::endl;
                    return false;
                }
            }
            // 可以选择是否处理符号链接等其他类型文件
        }
        return true;
    }
    catch (const fs::filesystem_error& e)
    {
        std::cerr << "复制目录失败: " << e.what() << std::endl;
        return false;
    }
}


std::string KMPackageManager::processDeleteLine(const std::string& line, KMRef& ref)
{
    std::string trimmedLine = line;
    while (!trimmedLine.empty() && (trimmedLine.back() == '\n' || trimmedLine.back() == '\r'))
    {
        trimmedLine.pop_back();
    }

    if (trimmedLine.empty())
    {
        return trimmedLine;
    }

    size_t slashCount = 0;
    size_t thirdSlashPos = std::string::npos;

    for (size_t i = 0; i < trimmedLine.length(); ++i)
    {
        if (trimmedLine[i] == '/')
        {
            slashCount++;
            if (slashCount == 3)
            {
                thirdSlashPos = i;
                break;
            }
        }
    }

    // 构建新路径
    std::stringstream ss;
    ss << "/opt/kaiming/layers/"
       << ref.channel << "/" << ref.arch << "/" << ref.kind << "/" << ref.id << "/" << ref.module << "/" << ref.findPreVersion;

    if (thirdSlashPos != std::string::npos && thirdSlashPos + 1 < trimmedLine.length())
    {
        ss << trimmedLine.substr(thirdSlashPos);
    }

    return ss.str();
}

bool KMPackageManager::processDeleteFile(const std::string& filename, KMRef& ref)
{
    std::ifstream inputFile(filename);
    if (!inputFile.is_open())
    {
        std::cerr << "Error: Cannot open file " << filename << " for reading." << std::endl;
        return false;
    }
    
    std::vector<std::string> lines;
    std::string line;
    
    while (std::getline(inputFile, line))
    {
        if (!line.empty())
        {
            std::string processedLine = processDeleteLine(line, ref);
            if (fs::exists(processedLine) && fs::is_regular_file(processedLine))
            {
                std::remove(processedLine.c_str());
            }
        }
    }

    inputFile.close();
    
    return true;
}

void KMPackageManager::upgradeDirectory(const std::string& newDir, const std::string& oldDir) {
    // 确保目录路径格式正确
    std::string newBase = newDir;
    std::string oldBase = oldDir;
    
    if (newBase.back() != '/') newBase += "/";
    if (oldBase.back() != '/') oldBase += "/";

    std::cout << "开始升级: " << newBase << " -> " << oldBase << std::endl;

    // 遍历新目录中的所有文件
    for (const auto& entry : fs::recursive_directory_iterator(newBase))
    {
        if (entry.is_regular_file() && entry.path().extension() == ".xdelta")
        {
            // 获取.xdelta文件的完整路径
            std::string deltaFile = entry.path().string();
            
            // 获取相对于新目录的相对路径
            std::string relativePath = deltaFile.substr(newBase.length());
            
            // 去除.xdelta后缀得到目标文件名
            std::string targetFile = relativePath.substr(0, relativePath.find(".xdelta"));
            
            // 构建旧文件路径
            std::string oldFile = oldBase + targetFile;
            
            // 构建新文件路径（与.xdelta文件在同一目录）
            std::string newFile = newBase + targetFile;
            
            // 确保目标目录存在
            std::string newFileDir = fs::path(newFile).parent_path().string();
            if (!fs::exists(newFileDir)) {
                fs::create_directories(newFileDir);
            }

            // 获取原文件权限
            struct stat oldFileStat;
            mode_t oldPermissions = 0644; // 默认权限
            if (stat(oldFile.c_str(), &oldFileStat) == 0) {
                oldPermissions = oldFileStat.st_mode;
            }

            // 执行xdelta3命令
            std::string command = "xdelta3 -d -f -s \"" + oldFile + "\" \"" + deltaFile + "\" \"" + newFile + "\"";
            
            int result = std::system(command.c_str());
            
            if (result == 0) {
                // 设置新文件权限与原文件相同
                chmod(newFile.c_str(), oldPermissions);
                // 删除差量文件
                std::remove(deltaFile.c_str());
            } else {
                std::cout << "✗ 失败: " << newFile << " (错误码: " << result << ")" << std::endl;
            }
        }
    }
    
    std::cout << "升级完成!" << std::endl;
}
