#include "BootEditorTab.h"
#include "../../Framework/PrivilegeElevationPrompt.h"

#include <QApplication>
#include <QCheckBox>
#include <QClipboard>
#include <QComboBox>
#include <QCoreApplication>
#include <QDateTime>
#include <QElapsedTimer>
#include <QEventLoop>
#include <QFileDialog>
#include <QInputDialog>
#include <QLabel>
#include <QLineEdit>
#include <QMessageBox>
#include <QPlainTextEdit>
#include <QPointer>
#include <QProcess>
#include <QRegularExpression>
#include <QSpinBox>
#include <QTableWidget>
#include <QTableWidgetItem>
#include <QTextCursor>
#include <QThreadPool>
#include <QTimer>
#include <QVariant>

#include <atomic>

namespace
{
    // 分离文件内重复常量：
    // - kColumnIdentifier 与主文件保持一致；
    // - kDefaultCommandTimeoutMs 与主文件保持一致。
    constexpr int kColumnIdentifier = 0;
    constexpr int kDefaultCommandTimeoutMs = 30000;

    // parseBoolText：
    // - 从字符串解释布尔值；
    // - 识别失败时回退 defaultValue。
    bool parseBoolText(const QString& rawText, const bool defaultValue)
    {
        const QString normalizedText = rawText.trimmed().toLower();
        if (normalizedText == QStringLiteral("yes")
            || normalizedText == QStringLiteral("on")
            || normalizedText == QStringLiteral("true")
            || normalizedText == QStringLiteral("1")
            || normalizedText == QStringLiteral("enabled"))
        {
            return true;
        }
        if (normalizedText == QStringLiteral("no")
            || normalizedText == QStringLiteral("off")
            || normalizedText == QStringLiteral("false")
            || normalizedText == QStringLiteral("0")
            || normalizedText == QStringLiteral("disabled"))
        {
            return false;
        }
        return defaultValue;
    }

    // ===================== 只读枚举异步化支撑 =====================
    // 背景：
    // - BootEditorTab 构造函数直接调用 refreshBcdEntries()，而构造函数与 refreshBcdEntries()
    //   都位于 BootEditorTab.cpp，不在本次可修改范围内，无法把首轮枚举整体挪出构造期；
    // - 因此改在 runBcdEdit 内部拦截“刷新专用只读枚举”：真正的 bcdedit 交给线程池执行，
    //   调用方立刻拿到由上一轮缓存文本组成的占位结果，后台结果回投 UI 线程后再刷新一次；
    // - 跨调用状态用 QObject 动态属性承载，既避开不可修改的头文件，
    //   又保证控件析构时状态随对象一起消失，不会留下文件级残留。

    // kEnumPendingGenerationProperty：进行中的枚举请求代号，属性缺失或为 0 表示当前没有后台任务。
    constexpr char kEnumPendingGenerationProperty[] = "ks_bcdEnumPendingGeneration";
    // kEnumReadyResultProperty：后台回投后暂存的枚举结果，等待下一次同步调用取走。
    constexpr char kEnumReadyResultProperty[] = "ks_bcdEnumReadyResult";

    // 枚举结果 QVariantMap 字段名：
    // - 后台线程写入、UI 线程读取；
    // - 集中定义避免两侧键名拼写漂移。
    constexpr char kEnumResultStartSucceededKey[] = "startSucceeded";
    constexpr char kEnumResultTimeoutKey[] = "timeout";
    constexpr char kEnumResultExitCodeKey[] = "exitCode";
    constexpr char kEnumResultStandardOutputKey[] = "standardOutput";
    constexpr char kEnumResultStandardErrorKey[] = "standardError";

    // kProcessStartTimeoutMs：等待子进程创建完成的上限（毫秒）。
    constexpr int kProcessStartTimeoutMs = 3000;
    // kProcessKillWaitMs：强杀后回收进程对象的等待上限（毫秒）。
    constexpr int kProcessKillWaitMs = 1000;
    // kBackgroundWaitSliceMs：后台等待的分段粒度（毫秒），用于定期复查进程状态与应用退出标记。
    constexpr int kBackgroundWaitSliceMs = 200;

    // g_enumRequestGenerationCounter：
    // - 作用：全局单调递增的枚举请求代号，用于淘汰已被新请求取代的旧结果；
    // - 说明：目前只在 UI 线程自增，用原子类型是为了防止后续被误用到其它线程。
    std::atomic<quint64> g_enumRequestGenerationCounter{ 0 };

    // g_placeholderLogOwnerObject：
    // - 作用：记录“最近一次 runBcdEdit 返回的是异步占位结果”的控件地址；
    // - 说明：appendCommandLog 读到同一地址时跳过本次日志，避免把缓存文本重复写进原始输出区；
    // - 线程：只在 UI 线程读写。
    const void* g_placeholderLogOwnerObject = nullptr;

    // g_synchronousCommandDepth：
    // - 作用：记录当前有几层写命令正卡在嵌套事件循环里等待；
    // - 说明：>0 时禁止异步枚举结果触发刷新，避免重建表格顺带改写用户正在提交的编辑框内容；
    // - 线程：只在 UI 线程读写。
    int g_synchronousCommandDepth = 0;

    // isBcdRefreshEnumRequest：
    // - 作用：判断本次调用是否为刷新流程专用的整表只读枚举；
    // - 入参 argumentList：bcdedit 参数列表；入参 commandDescription：调用方描述文本；
    // - 返回：参数与描述同时匹配刷新专用枚举时返回 true，用户自定义命令不会被误判。
    bool isBcdRefreshEnumRequest(const QStringList& argumentList, const QString& commandDescription)
    {
        if (commandDescription != QStringLiteral("枚举全部 BCD 条目"))
        {
            return false;
        }
        return argumentList.size() == 3
            && argumentList.at(0).compare(QStringLiteral("/enum"), Qt::CaseInsensitive) == 0
            && argumentList.at(1).compare(QStringLiteral("all"), Qt::CaseInsensitive) == 0
            && argumentList.at(2).compare(QStringLiteral("/v"), Qt::CaseInsensitive) == 0;
    }

    // runBcdEditInCallingThread：
    // - 作用：在当前线程内完整执行一次 bcdedit，产出可跨线程搬运的纯值类型结果；
    // - 入参 argumentList：bcdedit 参数列表；入参 timeoutMs：整体执行超时上限（毫秒）；
    // - 返回：含启动状态、超时标记、退出码与标准输出/标准错误文本的 QVariantMap。
    QVariantMap runBcdEditInCallingThread(const QStringList& argumentList, const int timeoutMs)
    {
        QVariantMap resultMap;
        resultMap.insert(QString::fromLatin1(kEnumResultStartSucceededKey), false);
        resultMap.insert(QString::fromLatin1(kEnumResultTimeoutKey), false);
        resultMap.insert(QString::fromLatin1(kEnumResultExitCodeKey), -1);
        resultMap.insert(QString::fromLatin1(kEnumResultStandardOutputKey), QString());
        resultMap.insert(QString::fromLatin1(kEnumResultStandardErrorKey), QString());

        // 后台线程内刻意不设父对象：QProcess 生命周期完全由本函数栈决定，不跨线程共享。
        QProcess backgroundProcess;
        backgroundProcess.setProgram(QStringLiteral("bcdedit"));
        backgroundProcess.setArguments(argumentList);
        backgroundProcess.setProcessChannelMode(QProcess::SeparateChannels);
        backgroundProcess.start();

        if (!backgroundProcess.waitForStarted(kProcessStartTimeoutMs))
        {
            resultMap.insert(
                QString::fromLatin1(kEnumResultStandardErrorKey),
                backgroundProcess.errorString());
            return resultMap;
        }
        resultMap.insert(QString::fromLatin1(kEnumResultStartSucceededKey), true);

        // 分段等待：
        // - 后台线程没有事件循环，waitForFinished 不会重入 UI，也就不需要 processEvents；
        // - 切成小片是为了在应用退出时尽快松手，避免线程池收尾阶段被长命令拖住。
        const int effectiveTimeoutMs = timeoutMs > 0 ? timeoutMs : kDefaultCommandTimeoutMs;
        QElapsedTimer elapsedTimer;
        elapsedTimer.start();
        bool processFinished = false;
        while (true)
        {
            if (backgroundProcess.waitForFinished(kBackgroundWaitSliceMs)
                || backgroundProcess.state() == QProcess::NotRunning)
            {
                processFinished = true;
                break;
            }
            if (elapsedTimer.elapsed() >= effectiveTimeoutMs || QCoreApplication::closingDown())
            {
                break;
            }
        }

        if (processFinished)
        {
            resultMap.insert(QString::fromLatin1(kEnumResultExitCodeKey), backgroundProcess.exitCode());
        }
        else
        {
            backgroundProcess.kill();
            backgroundProcess.waitForFinished(kProcessKillWaitMs);
            resultMap.insert(QString::fromLatin1(kEnumResultTimeoutKey), true);
        }

        resultMap.insert(
            QString::fromLatin1(kEnumResultStandardOutputKey),
            QString::fromLocal8Bit(backgroundProcess.readAllStandardOutput()));
        resultMap.insert(
            QString::fromLatin1(kEnumResultStandardErrorKey),
            QString::fromLocal8Bit(backgroundProcess.readAllStandardError()));
        return resultMap;
    }
}

void BootEditorTab::applySelectedEntryChanges()
{
    const BcdEntry* selectedEntry = currentEntry();
    if (selectedEntry == nullptr)
    {
        QMessageBox::information(this, QStringLiteral("引导编辑器"), QStringLiteral("请先选择一个引导条目。"));
        return;
    }

    const QString identifierText = selectedEntry->identifierText.trimmed();
    if (identifierText.isEmpty())
    {
        QMessageBox::warning(this, QStringLiteral("引导编辑器"), QStringLiteral("当前条目标识符为空，无法写入。"));
        return;
    }

    // 批量写入策略：
    // - 按字段逐条执行 bcdedit /set；
    // - 任一步失败就终止后续写入，避免状态部分落地。
    if (!m_descriptionEdit->text().trimmed().isEmpty())
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("description"), m_descriptionEdit->text().trimmed() },
            QStringLiteral("写入 description"),
            false))
        {
            return;
        }
    }
    if (!m_deviceEdit->text().trimmed().isEmpty())
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("device"), m_deviceEdit->text().trimmed() },
            QStringLiteral("写入 device"),
            false))
        {
            return;
        }
    }
    if (!m_osDeviceEdit->text().trimmed().isEmpty())
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("osdevice"), m_osDeviceEdit->text().trimmed() },
            QStringLiteral("写入 osdevice"),
            false))
        {
            return;
        }
    }
    if (!m_pathEdit->text().trimmed().isEmpty())
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("path"), m_pathEdit->text().trimmed() },
            QStringLiteral("写入 path"),
            false))
        {
            return;
        }
    }
    if (!m_systemRootEdit->text().trimmed().isEmpty())
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("systemroot"), m_systemRootEdit->text().trimmed() },
            QStringLiteral("写入 systemroot"),
            false))
        {
            return;
        }
    }
    if (!m_localeEdit->text().trimmed().isEmpty())
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("locale"), m_localeEdit->text().trimmed() },
            QStringLiteral("写入 locale"),
            false))
        {
            return;
        }
    }

    const QString bootMenuPolicyValue = m_bootMenuPolicyCombo->currentData().toString().trimmed();
    if (!bootMenuPolicyValue.isEmpty())
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("bootmenupolicy"), bootMenuPolicyValue },
            QStringLiteral("写入 bootmenupolicy"),
            false))
        {
            return;
        }
    }

    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("testsigning"), boolToBcdOnOff(m_testSigningCheck->isChecked()) },
        QStringLiteral("写入 testsigning"),
        false))
    {
        return;
    }
    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("nointegritychecks"), boolToBcdOnOff(m_noIntegrityCheck->isChecked()) },
        QStringLiteral("写入 nointegritychecks"),
        false))
    {
        return;
    }
    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("debug"), boolToBcdOnOff(m_debugCheck->isChecked()) },
        QStringLiteral("写入 debug"),
        false))
    {
        return;
    }
    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("bootlog"), boolToBcdYesNo(m_bootLogCheck->isChecked()) },
        QStringLiteral("写入 bootlog"),
        false))
    {
        return;
    }
    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("basevideo"), boolToBcdYesNo(m_baseVideoCheck->isChecked()) },
        QStringLiteral("写入 basevideo"),
        false))
    {
        return;
    }
    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("recoveryenabled"), boolToBcdYesNo(m_recoveryEnabledCheck->isChecked()) },
        QStringLiteral("写入 recoveryenabled"),
        false))
    {
        return;
    }

    // safeboot 处理：
    // - 关闭模式：删除 safeboot 与 safebootalternateshell；
    // - 其余模式：按组合值写入。
    const QString safeBootModeValue = m_safeBootCombo->currentData().toString().trimmed().toLower();

    // deleteValueWithMissingTolerance：
    // - 统一处理 deletevalue 的返回；
    // - 若仅因“字段不存在”失败则视为目标状态已满足；
    // - 其它失败直接中止，避免最终误报“写入完成”。
    const auto deleteValueWithMissingTolerance = [this, &identifierText](const QString& elementName) -> bool
        {
            const QString operationText = QStringLiteral("删除 %1").arg(elementName);
            const BcdCommandResult deleteResult = runBcdEdit(
                QStringList{
                    QStringLiteral("/deletevalue"),
                    identifierText,
                    elementName
                },
                kDefaultCommandTimeoutMs,
                operationText);
            appendCommandLog(
                QStringLiteral("bcdedit /deletevalue %1 %2").arg(identifierText, elementName),
                deleteResult);

            if (deleteResult.startSucceeded && !deleteResult.timeout && deleteResult.exitCode == 0)
            {
                return true;
            }

            const QString outputLowerText = deleteResult.mergedOutputText.toLower();
            const bool likelyMissingElement =
                outputLowerText.contains(QStringLiteral("not found"))
                || outputLowerText.contains(QStringLiteral("cannot find"))
                || outputLowerText.contains(QStringLiteral("does not exist"))
                || deleteResult.mergedOutputText.contains(QStringLiteral("找不到"))
                || deleteResult.mergedOutputText.contains(QStringLiteral("不存在"))
                || deleteResult.mergedOutputText.contains(QStringLiteral("未找到"));

            if (likelyMissingElement)
            {
                kLogEvent warnEvent;
                warn << warnEvent
                    << "[BootEditor] deletevalue 字段不存在，按目标状态继续: element="
                    << elementName.toStdString()
                    << ", identifier="
                    << identifierText.toStdString()
                    << eol;
                return true;
            }

            QMessageBox::warning(
                this,
                QStringLiteral("引导编辑器"),
                QStringLiteral("%1失败：\n%2")
                .arg(operationText, deleteResult.mergedOutputText.trimmed()));
            return false;
        };

    if (safeBootModeValue == QStringLiteral("off"))
    {
        if (!deleteValueWithMissingTolerance(QStringLiteral("safeboot")))
        {
            return;
        }
        if (!deleteValueWithMissingTolerance(QStringLiteral("safebootalternateshell")))
        {
            return;
        }
    }
    else if (safeBootModeValue == QStringLiteral("minimal"))
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("safeboot"), QStringLiteral("minimal") },
            QStringLiteral("写入 safeboot=minimal"),
            false))
        {
            return;
        }
        if (!deleteValueWithMissingTolerance(QStringLiteral("safebootalternateshell")))
        {
            return;
        }
    }
    else if (safeBootModeValue == QStringLiteral("network"))
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("safeboot"), QStringLiteral("network") },
            QStringLiteral("写入 safeboot=network"),
            false))
        {
            return;
        }
        if (!deleteValueWithMissingTolerance(QStringLiteral("safebootalternateshell")))
        {
            return;
        }
    }
    else if (safeBootModeValue == QStringLiteral("alternateshell"))
    {
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("safeboot"), QStringLiteral("minimal") },
            QStringLiteral("写入 safeboot=minimal"),
            false))
        {
            return;
        }
        if (!runBcdAndExpectSuccess(
            QStringList{ QStringLiteral("/set"), identifierText, QStringLiteral("safebootalternateshell"), QStringLiteral("yes") },
            QStringLiteral("写入 safebootalternateshell=yes"),
            false))
        {
            return;
        }
    }

    QMessageBox::information(this, QStringLiteral("引导编辑器"), QStringLiteral("当前条目已写入完成。"));
    refreshBcdEntries();
}

void BootEditorTab::applyBootManagerChanges()
{
    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/timeout"), QString::number(m_timeoutSpin->value()) },
        QStringLiteral("写入 timeout"),
        true))
    {
        return;
    }
    refreshBcdEntries();
}

void BootEditorTab::setLegacyBootForSelectedEntry()
{
    // 当前项传统引导：
    // - 对当前选中条目写入 bootmenupolicy Legacy；
    // - 成功后刷新列表与右侧详情。
    const BcdEntry* selectedEntry = currentEntry();
    if (selectedEntry == nullptr)
    {
        QMessageBox::information(this, QStringLiteral("传统引导"), QStringLiteral("请先选择一个引导条目。"));
        return;
    }

    if (!applyBootMenuPolicyByIdentifier(
        selectedEntry->identifierText.trimmed(),
        QStringLiteral("Legacy"),
        QStringLiteral("当前项启用传统引导")))
    {
        return;
    }
    refreshBcdEntries();
}

void BootEditorTab::setLegacyBootForDefaultEntry()
{
    // 默认项传统引导：
    // - 对 {bootmgr}.default 对应条目写入 bootmenupolicy Legacy；
    // - 若未读取到默认标识符则提示刷新后重试。
    const QString defaultIdentifierText = m_defaultIdentifierText.trimmed();
    if (defaultIdentifierText.isEmpty())
    {
        QMessageBox::warning(
            this,
            QStringLiteral("传统引导"),
            QStringLiteral("当前未识别到默认启动项，请先刷新 BCD。"));
        return;
    }

    if (!applyBootMenuPolicyByIdentifier(
        defaultIdentifierText,
        QStringLiteral("Legacy"),
        QStringLiteral("默认项启用传统引导")))
    {
        return;
    }
    refreshBcdEntries();
}

void BootEditorTab::setStandardBootForSelectedEntry()
{
    // 当前项恢复标准：
    // - 对当前选中条目写入 bootmenupolicy Standard；
    // - 用于回退“传统引导”快捷设置。
    const BcdEntry* selectedEntry = currentEntry();
    if (selectedEntry == nullptr)
    {
        QMessageBox::information(this, QStringLiteral("传统引导"), QStringLiteral("请先选择一个引导条目。"));
        return;
    }

    if (!applyBootMenuPolicyByIdentifier(
        selectedEntry->identifierText.trimmed(),
        QStringLiteral("Standard"),
        QStringLiteral("当前项恢复标准引导")))
    {
        return;
    }
    refreshBcdEntries();
}

void BootEditorTab::setSelectedAsDefaultEntry()
{
    const BcdEntry* selectedEntry = currentEntry();
    if (selectedEntry == nullptr)
    {
        QMessageBox::information(this, QStringLiteral("引导编辑器"), QStringLiteral("请先选择一个引导条目。"));
        return;
    }
    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/default"), selectedEntry->identifierText.trimmed() },
        QStringLiteral("设置默认启动项"),
        true))
    {
        return;
    }
    refreshBcdEntries();
}

void BootEditorTab::addSelectedToBootSequence()
{
    const BcdEntry* selectedEntry = currentEntry();
    if (selectedEntry == nullptr)
    {
        QMessageBox::information(this, QStringLiteral("引导编辑器"), QStringLiteral("请先选择一个引导条目。"));
        return;
    }
    if (!runBcdAndExpectSuccess(
        QStringList{
            QStringLiteral("/bootsequence"),
            selectedEntry->identifierText.trimmed(),
            QStringLiteral("/addfirst")
        },
        QStringLiteral("设置下一次启动项"),
        true))
    {
        return;
    }
    refreshBcdEntries();
}

void BootEditorTab::createCopyFromSelectedEntry()
{
    const BcdEntry* selectedEntry = currentEntry();
    if (selectedEntry == nullptr)
    {
        QMessageBox::information(this, QStringLiteral("引导编辑器"), QStringLiteral("请先选择一个引导条目。"));
        return;
    }

    const QString sourceDescription = readElementValue(
        *selectedEntry,
        QStringList{ QStringLiteral("description"), QStringLiteral("描述") });
    const QString defaultNewDescription = sourceDescription.trimmed().isEmpty()
        ? QStringLiteral("新建引导项")
        : QStringLiteral("%1 - 副本").arg(sourceDescription.trimmed());

    bool inputOk = false;
    const QString newDescription = QInputDialog::getText(
        this,
        QStringLiteral("复制引导项"),
        QStringLiteral("新引导项描述："),
        QLineEdit::Normal,
        defaultNewDescription,
        &inputOk).trimmed();
    if (!inputOk || newDescription.isEmpty())
    {
        return;
    }

    const BcdCommandResult copyResult = runBcdEdit(
        QStringList{
            QStringLiteral("/copy"),
            selectedEntry->identifierText.trimmed(),
            QStringLiteral("/d"),
            newDescription
        },
        kDefaultCommandTimeoutMs,
        QStringLiteral("复制引导项"));
    appendCommandLog(QStringLiteral("bcdedit /copy"), copyResult);

    if (!copyResult.startSucceeded || copyResult.timeout || copyResult.exitCode != 0)
    {
        QMessageBox::warning(
            this,
            QStringLiteral("复制引导项"),
            QStringLiteral("复制失败：\n%1").arg(copyResult.mergedOutputText.trimmed()));
        return;
    }

    // newIdentifierRegex：
    // - 从命令输出中抽取新 GUID；
    // - 成功后自动追加到 displayorder 尾部。
    const QRegularExpression newIdentifierRegex(QStringLiteral("\\{[^\\}\\s]+\\}"));
    QRegularExpressionMatchIterator matchIterator = newIdentifierRegex.globalMatch(copyResult.mergedOutputText);
    QString newIdentifierText;
    while (matchIterator.hasNext())
    {
        const QRegularExpressionMatch match = matchIterator.next();
        newIdentifierText = match.captured(0);
    }

    if (!newIdentifierText.trimmed().isEmpty())
    {
        runBcdAndExpectSuccess(
            QStringList{
                QStringLiteral("/displayorder"),
                newIdentifierText.trimmed(),
                QStringLiteral("/addlast")
            },
            QStringLiteral("追加到 displayorder"),
            false);
    }

    QMessageBox::information(this, QStringLiteral("复制引导项"), QStringLiteral("复制成功。"));
    refreshBcdEntries();
}

void BootEditorTab::deleteSelectedEntry()
{
    const BcdEntry* selectedEntry = currentEntry();
    if (selectedEntry == nullptr)
    {
        QMessageBox::information(this, QStringLiteral("引导编辑器"), QStringLiteral("请先选择一个引导条目。"));
        return;
    }

    const QString identifierText = selectedEntry->identifierText.trimmed();
    if (identifierText.compare(QStringLiteral("{bootmgr}"), Qt::CaseInsensitive) == 0)
    {
        QMessageBox::warning(this, QStringLiteral("删除引导项"), QStringLiteral("不允许删除 {bootmgr}。"));
        return;
    }
    if (identifierText.compare(QStringLiteral("{current}"), Qt::CaseInsensitive) == 0)
    {
        QMessageBox::warning(this, QStringLiteral("删除引导项"), QStringLiteral("不允许删除 {current}。"));
        return;
    }

    const int confirmResult = QMessageBox::warning(
        this,
        QStringLiteral("删除引导项"),
        QStringLiteral("即将删除条目：%1\n该操作不可撤销，是否继续？").arg(identifierText),
        QMessageBox::Yes | QMessageBox::No,
        QMessageBox::No);
    if (confirmResult != QMessageBox::Yes)
    {
        return;
    }

    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/delete"), identifierText },
        QStringLiteral("删除引导项"),
        true))
    {
        return;
    }
    refreshBcdEntries();
}

void BootEditorTab::exportBcdStore()
{
    const QString defaultFileName = QStringLiteral("bcd_backup_%1.bcd")
        .arg(QDateTime::currentDateTime().toString(QStringLiteral("yyyyMMdd_HHmmss")));
    const QString outputPath = QFileDialog::getSaveFileName(
        this,
        QStringLiteral("导出 BCD"),
        defaultFileName,
        QStringLiteral("BCD 文件 (*.bcd);;所有文件 (*.*)"));
    if (outputPath.trimmed().isEmpty())
    {
        return;
    }

    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/export"), outputPath },
        QStringLiteral("导出 BCD"),
        true))
    {
        return;
    }
}

void BootEditorTab::importBcdStore()
{
    const QString inputPath = QFileDialog::getOpenFileName(
        this,
        QStringLiteral("导入 BCD"),
        QString(),
        QStringLiteral("BCD 文件 (*.bcd);;所有文件 (*.*)"));
    if (inputPath.trimmed().isEmpty())
    {
        return;
    }

    const int confirmResult = QMessageBox::warning(
        this,
        QStringLiteral("导入 BCD"),
        QStringLiteral("导入会覆盖当前 BCD 存储，可能影响系统启动。\n确认继续吗？"),
        QMessageBox::Yes | QMessageBox::No,
        QMessageBox::No);
    if (confirmResult != QMessageBox::Yes)
    {
        return;
    }

    if (!runBcdAndExpectSuccess(
        QStringList{ QStringLiteral("/import"), inputPath },
        QStringLiteral("导入 BCD"),
        true))
    {
        return;
    }
    refreshBcdEntries();
}

void BootEditorTab::executeCustomCommand()
{
    const QString rawCommandText = m_customCommandEdit->text().trimmed();
    if (rawCommandText.isEmpty())
    {
        QMessageBox::information(this, QStringLiteral("自定义命令"), QStringLiteral("请输入命令参数。"));
        return;
    }

    // 参数解析策略：
    // - 支持“/set ...”；
    // - 也支持“bcdedit /set ...”，会自动去掉前缀 program。
    QStringList argumentList = QProcess::splitCommand(rawCommandText);
    if (!argumentList.isEmpty()
        && argumentList.front().compare(QStringLiteral("bcdedit"), Qt::CaseInsensitive) == 0)
    {
        argumentList.removeFirst();
    }
    if (argumentList.isEmpty())
    {
        QMessageBox::information(this, QStringLiteral("自定义命令"), QStringLiteral("未解析到有效参数。"));
        return;
    }

    const BcdCommandResult commandResult = runBcdEdit(
        argumentList,
        kDefaultCommandTimeoutMs,
        QStringLiteral("执行自定义 bcdedit"));
    appendCommandLog(QStringLiteral("bcdedit %1").arg(argumentList.join(' ')), commandResult);

    if (!commandResult.startSucceeded || commandResult.timeout || commandResult.exitCode != 0)
    {
        QMessageBox::warning(
            this,
            QStringLiteral("自定义命令"),
            QStringLiteral("命令执行失败：\n%1").arg(commandResult.mergedOutputText.trimmed()));
        return;
    }

    QMessageBox::information(this, QStringLiteral("自定义命令"), QStringLiteral("命令执行成功。"));

    const QString normalizedCommandText = rawCommandText.toLower();
    if (!normalizedCommandText.contains(QStringLiteral("/enum")))
    {
        refreshBcdEntries();
    }
}

void BootEditorTab::copySelectedRowToClipboard()
{
    const int rowIndex = m_entryTable->currentRow();
    if (rowIndex < 0)
    {
        return;
    }

    QStringList cellTextList;
    for (int colIndex = 0; colIndex < m_entryTable->columnCount(); ++colIndex)
    {
        QTableWidgetItem* item = m_entryTable->item(rowIndex, colIndex);
        cellTextList.push_back(item != nullptr ? item->text() : QString());
    }
    QApplication::clipboard()->setText(cellTextList.join('\t'));
}

int BootEditorTab::currentEntryIndex() const
{
    const int rowIndex = m_entryTable->currentRow();
    if (rowIndex < 0)
    {
        return -1;
    }
    QTableWidgetItem* identifierItem = m_entryTable->item(rowIndex, kColumnIdentifier);
    if (identifierItem == nullptr)
    {
        return -1;
    }
    return identifierItem->data(Qt::UserRole).toInt();
}

const BootEditorTab::BcdEntry* BootEditorTab::currentEntry() const
{
    const int index = currentEntryIndex();
    if (index < 0 || index >= static_cast<int>(m_entryList.size()))
    {
        return nullptr;
    }
    return &m_entryList[static_cast<std::size_t>(index)];
}

bool BootEditorTab::entryMatchesFilter(const BcdEntry& entry) const
{
    const QString keywordText = m_filterEdit->text().trimmed();
    if (keywordText.isEmpty())
    {
        return true;
    }
    const QString lowerKeyword = keywordText.toLower();
    const QString descriptionText = readElementValue(entry, QStringList{
        QStringLiteral("description"),
        QStringLiteral("描述")
        });
    const QString pathText = readElementValue(entry, QStringList{
        QStringLiteral("path"),
        QStringLiteral("路径")
        });
    const QString deviceText = readElementValue(entry, QStringList{
        QStringLiteral("device"),
        QStringLiteral("设备")
        });

    return entry.identifierText.toLower().contains(lowerKeyword)
        || entry.objectTypeText.toLower().contains(lowerKeyword)
        || descriptionText.toLower().contains(lowerKeyword)
        || pathText.toLower().contains(lowerKeyword)
        || deviceText.toLower().contains(lowerKeyword);
}

QString BootEditorTab::readElementValue(
    const BcdEntry& entry,
    const QStringList& candidateKeyList) const
{
    // 只做精确键匹配：
    // - 避免 device/osdevice 等相似字段被 contains 误命中；
    // - 若字段缺失则返回空，交给调用方决定后续行为。
    for (const QString& candidateRawKey : candidateKeyList)
    {
        const QString normalizedCandidateKey = normalizeElementKey(candidateRawKey);
        if (entry.elementMap.contains(normalizedCandidateKey))
        {
            return entry.elementMap.value(normalizedCandidateKey);
        }
    }
    return QString();
}

bool BootEditorTab::readElementBool(
    const BcdEntry& entry,
    const QStringList& candidateKeyList,
    const bool defaultValue) const
{
    const QString valueText = readElementValue(entry, candidateKeyList);
    return parseBoolText(valueText, defaultValue);
}

void BootEditorTab::appendCommandLog(
    const QString& commandTitle,
    const BcdCommandResult& commandResult)
{
    // 异步占位结果不落日志：
    // - 占位结果只是把上一轮缓存文本原样交还给刷新流程，用于让界面维持既有内容；
    // - 后台真实结果回投后会再走一次刷新，那一次才写入日志，保证一次刷新只有一条记录。
    if (g_placeholderLogOwnerObject == this)
    {
        g_placeholderLogOwnerObject = nullptr;
        return;
    }

    // 日志块格式：
    // - 首行展示时间与命令标题；
    // - 第二行开始展示原始输出；
    // - 末尾追加执行状态摘要。
    const QString timestampText = QDateTime::currentDateTime().toString(QStringLiteral("yyyy-MM-dd HH:mm:ss"));
    QString statusText = QStringLiteral("start=%1, timeout=%2, exit=%3")
        .arg(commandResult.startSucceeded ? QStringLiteral("true") : QStringLiteral("false"))
        .arg(commandResult.timeout ? QStringLiteral("true") : QStringLiteral("false"))
        .arg(commandResult.exitCode);
    QString logText = QStringLiteral("[%1] %2\n%3\n[%4]\n\n")
        .arg(timestampText)
        .arg(commandTitle)
        .arg(commandResult.mergedOutputText.trimmed())
        .arg(statusText);

    m_rawOutputEdit->moveCursor(QTextCursor::End);
    m_rawOutputEdit->insertPlainText(logText);
    m_rawOutputEdit->moveCursor(QTextCursor::End);
}

BootEditorTab::BcdCommandResult BootEditorTab::runBcdEdit(
    const QStringList& argumentList,
    const int timeoutMs,
    const QString& commandDescription)
{
    // 进入时先清掉占位日志标记：
    // - 正常流程里 appendCommandLog 会紧跟着消费掉它；
    // - 万一某个调用方没有写日志，这里兜底，避免误抑制下一条真实日志。
    g_placeholderLogOwnerObject = nullptr;

    BcdCommandResult result;
    const QString commandVerb = argumentList.value(0).trimmed().toLower();
    const bool readOnlyCommand = commandVerb == QStringLiteral("/enum") ||
        commandVerb == QStringLiteral("/enumall") ||
        commandVerb == QStringLiteral("/v");
    if (!readOnlyCommand && !ks::ui::isCurrentProcessElevated())
    {
        (void)ks::ui::requestAdministratorRestartForFeature(
            this,
            QStringLiteral("修改 BCD 启动配置"));
        result.startSucceeded = false;
        result.standardErrorText = QStringLiteral("需要管理员权限。请在管理员实例中重试。");
        result.mergedOutputText = result.standardErrorText;
        return result;
    }

    // ============ 刷新专用只读枚举：整段交给线程池，UI 线程零阻塞 ============
    if (isBcdRefreshEnumRequest(argumentList, commandDescription))
    {
        // 第一步：后台结果已经回投时直接取走，按同步语义返回，让刷新流程正常填表并写日志。
        const QVariant readyResultVariant = property(kEnumReadyResultProperty);
        if (readyResultVariant.isValid())
        {
            setProperty(kEnumReadyResultProperty, QVariant());

            const QVariantMap readyResultMap = readyResultVariant.toMap();
            result.startSucceeded =
                readyResultMap.value(QString::fromLatin1(kEnumResultStartSucceededKey)).toBool();
            result.timeout =
                readyResultMap.value(QString::fromLatin1(kEnumResultTimeoutKey)).toBool();
            result.exitCode =
                readyResultMap.value(QString::fromLatin1(kEnumResultExitCodeKey)).toInt();
            result.standardOutputText =
                readyResultMap.value(QString::fromLatin1(kEnumResultStandardOutputKey)).toString();
            result.standardErrorText =
                readyResultMap.value(QString::fromLatin1(kEnumResultStandardErrorKey)).toString();
            result.mergedOutputText = result.standardOutputText;
            if (!result.standardErrorText.trimmed().isEmpty())
            {
                if (!result.mergedOutputText.trimmed().isEmpty())
                {
                    result.mergedOutputText += QStringLiteral("\n");
                }
                result.mergedOutputText += result.standardErrorText;
            }

            kLogEvent asyncResultEvent;
            if (!result.startSucceeded)
            {
                err << asyncResultEvent
                    << "[BootEditor] 命令启动失败: "
                    << commandDescription.toStdString()
                    << ", error="
                    << result.standardErrorText.toStdString()
                    << eol;
            }
            else if (result.timeout)
            {
                err << asyncResultEvent
                    << "[BootEditor] 命令执行超时: "
                    << commandDescription.toStdString()
                    << ", timeoutMs="
                    << timeoutMs
                    << eol;
            }
            else if (result.exitCode == 0)
            {
                info << asyncResultEvent
                    << "[BootEditor] 命令执行完成: "
                    << commandDescription.toStdString()
                    << ", exitCode="
                    << result.exitCode
                    << eol;
            }
            else
            {
                warn << asyncResultEvent
                    << "[BootEditor] 命令返回非零: "
                    << commandDescription.toStdString()
                    << ", exitCode="
                    << result.exitCode
                    << eol;
            }
            return result;
        }

        // 第二步：没有现成结果就派发后台任务；已有任务在跑时直接复用，避免重复拉起 bcdedit。
        if (property(kEnumPendingGenerationProperty).toULongLong() == 0)
        {
            // requestGeneration 用途：淘汰已被新请求取代的旧结果。
            const quint64 requestGeneration = ++g_enumRequestGenerationCounter;
            setProperty(
                kEnumPendingGenerationProperty,
                QVariant::fromValue<qulonglong>(requestGeneration));

            // guardedSelf 用途：后台任务可能晚于控件销毁，回投前必须验证生命周期。
            const QPointer<BootEditorTab> guardedSelf(this);
            const QStringList requestArgumentList = argumentList;
            const int requestTimeoutMs = timeoutMs;
            QThreadPool::globalInstance()->start(
                [guardedSelf, requestGeneration, requestArgumentList, requestTimeoutMs]()
                {
                    // 后台线程只做纯数据采集，产出可跨线程搬运的值类型。
                    const QVariantMap collectedResultMap =
                        runBcdEditInCallingThread(requestArgumentList, requestTimeoutMs);

                    QCoreApplication* const appInstance = QCoreApplication::instance();
                    if (appInstance == nullptr)
                    {
                        return;
                    }
                    QMetaObject::invokeMethod(
                        appInstance,
                        [guardedSelf, requestGeneration, collectedResultMap]()
                        {
                            if (guardedSelf == nullptr)
                            {
                                return;
                            }
                            const quint64 currentPendingGeneration =
                                guardedSelf->property(kEnumPendingGenerationProperty).toULongLong();
                            if (currentPendingGeneration != requestGeneration)
                            {
                                return;
                            }
                            guardedSelf->setProperty(kEnumPendingGenerationProperty, QVariant());
                            if (g_synchronousCommandDepth > 0)
                            {
                                // 此刻正卡在写命令的同步等待里：
                                // - 这份快照拍摄于写入之前，本来就已过期；
                                // - 现在刷新还会重建表格并改写用户正在提交的编辑框内容；
                                // - 直接丢弃，写入流程收尾时会自行调用 refreshBcdEntries 重取。
                                return;
                            }
                            guardedSelf->setProperty(kEnumReadyResultProperty, collectedResultMap);
                            guardedSelf->refreshBcdEntries();
                        });
                });
        }

        // 第三步：立刻返回占位结果。
        // - 沿用上一轮原始枚举文本，等待期间表格与编辑区保持既有内容，不会闪成空表；
        // - 标记占位日志归属，避免把缓存文本重复写进“原始输出”区。
        result.startSucceeded = true;
        result.timeout = false;
        result.exitCode = 0;
        result.standardOutputText = m_lastEnumRawText;
        result.mergedOutputText = m_lastEnumRawText;
        g_placeholderLogOwnerObject = this;

        if (m_lastEnumRawText.trimmed().isEmpty() && m_statusLabel != nullptr)
        {
            // 首轮加载没有历史数据可沿用，refreshBcdEntries 会写出“总条目 0”的摘要；
            // 这里在下一轮事件循环把状态栏改回“尚未加载”，避免被误读成系统真的没有引导项。
            QTimer::singleShot(0, this, [this]()
                {
                    if (m_statusLabel == nullptr)
                    {
                        return;
                    }
                    if (property(kEnumPendingGenerationProperty).toULongLong() == 0)
                    {
                        return;
                    }
                    m_statusLabel->setText(QStringLiteral("状态：尚未加载 BCD 数据"));
                });
        }
        return result;
    }

    // ============ 其余命令：信号驱动的有界等待 ============
    // 说明：
    // - 写操作的调用方按返回值决定是否继续后续写入，必须保留同步语义；
    // - 但等待方式不再是 waitForStarted 硬阻塞 + waitForFinished/processEvents 忙轮询：
    //   进程结束、启动失败与超时全部由信号驱动，嵌套事件循环排除用户输入事件，
    //   堵住等待期间点击其它页签触发懒加载重入构造的路径。
    QProcess process; // 刻意不设父对象：嵌套事件循环期间父控件若被销毁会造成悬垂。

    process.setProgram(QStringLiteral("bcdedit"));
    process.setArguments(argumentList);
    process.setProcessChannelMode(QProcess::SeparateChannels);

    process.start();

    // buildStartFailureResult：
    // - 作用：统一收敛“进程未能启动”的结果填充与错误日志；
    // - 返回：已填好错误信息的命令结果。
    const auto buildStartFailureResult = [&result, &process, &commandDescription]() -> BcdCommandResult
        {
            result.startSucceeded = false;
            result.standardErrorText = process.errorString();
            result.mergedOutputText = result.standardErrorText;
            kLogEvent startFailedEvent;
            err << startFailedEvent
                << "[BootEditor] 命令启动失败: "
                << commandDescription.toStdString()
                << ", error="
                << result.standardErrorText.toStdString()
                << eol;
            return result;
        };

    if (process.state() == QProcess::NotRunning)
    {
        // CreateProcess 直接失败时 QProcess 会同步退回 NotRunning，无需进入等待。
        return buildStartFailureResult();
    }

    QEventLoop waitEventLoop;
    QTimer waitTimeoutTimer;
    waitTimeoutTimer.setSingleShot(true);
    waitTimeoutTimer.setInterval(timeoutMs > 0 ? timeoutMs : kDefaultCommandTimeoutMs);

    bool processFailedToStart = false;
    bool waitTimedOut = false;

    QObject::connect(&process, &QProcess::finished, &waitEventLoop,
        [&waitEventLoop](int, QProcess::ExitStatus)
        {
            waitEventLoop.quit();
        });
    QObject::connect(&process, &QProcess::errorOccurred, &waitEventLoop,
        [&waitEventLoop, &processFailedToStart](const QProcess::ProcessError processError)
        {
            if (processError != QProcess::FailedToStart)
            {
                return;
            }
            processFailedToStart = true;
            waitEventLoop.quit();
        });
    QObject::connect(&waitTimeoutTimer, &QTimer::timeout, &waitEventLoop,
        [&waitEventLoop, &waitTimedOut]()
        {
            waitTimedOut = true;
            waitEventLoop.quit();
        });

    waitTimeoutTimer.start();
    if (process.state() != QProcess::NotRunning)
    {
        // 嵌套等待期间标记同步深度：
        // - 排除用户输入已经挡住“等待中点击其它页签触发懒加载重入构造”；
        // - 深度标记再挡住异步枚举结果在此刻回投刷新，双保险。
        ++g_synchronousCommandDepth;
        waitEventLoop.exec(QEventLoop::ExcludeUserInputEvents);
        --g_synchronousCommandDepth;
    }
    waitTimeoutTimer.stop();

    if (processFailedToStart)
    {
        return buildStartFailureResult();
    }
    result.startSucceeded = true;

    if (waitTimedOut)
    {
        result.timeout = true;
        process.kill();
        process.waitForFinished(kProcessKillWaitMs);

        result.standardOutputText = QString::fromLocal8Bit(process.readAllStandardOutput());
        result.standardErrorText = QString::fromLocal8Bit(process.readAllStandardError());
        result.mergedOutputText = result.standardOutputText + QStringLiteral("\n") + result.standardErrorText;

        kLogEvent timeoutEvent;
        err << timeoutEvent
            << "[BootEditor] 命令执行超时: "
            << commandDescription.toStdString()
            << ", timeoutMs="
            << timeoutMs
            << eol;
        return result;
    }

    result.exitCode = process.exitCode();
    result.standardOutputText = QString::fromLocal8Bit(process.readAllStandardOutput());
    result.standardErrorText = QString::fromLocal8Bit(process.readAllStandardError());
    result.mergedOutputText = result.standardOutputText;
    if (!result.standardErrorText.trimmed().isEmpty())
    {
        if (!result.mergedOutputText.trimmed().isEmpty())
        {
            result.mergedOutputText += QStringLiteral("\n");
        }
        result.mergedOutputText += result.standardErrorText;
    }

    kLogEvent event;
    if (result.exitCode == 0)
    {
        info << event
            << "[BootEditor] 命令执行完成: "
            << commandDescription.toStdString()
            << ", exitCode="
            << result.exitCode
            << eol;
    }
    else
    {
        warn << event
            << "[BootEditor] 命令返回非零: "
            << commandDescription.toStdString()
            << ", exitCode="
            << result.exitCode
            << eol;
    }
    return result;
}

bool BootEditorTab::runBcdAndExpectSuccess(
    const QStringList& argumentList,
    const QString& operationText,
    const bool showSuccessToast)
{
    const BcdCommandResult result = runBcdEdit(argumentList, kDefaultCommandTimeoutMs, operationText);
    appendCommandLog(QStringLiteral("bcdedit %1").arg(argumentList.join(' ')), result);

    if (!result.startSucceeded)
    {
        QMessageBox::warning(
            this,
            QStringLiteral("引导编辑器"),
            QStringLiteral("%1失败：命令未能启动。\n%2").arg(operationText, result.mergedOutputText.trimmed()));
        return false;
    }
    if (result.timeout)
    {
        QMessageBox::warning(
            this,
            QStringLiteral("引导编辑器"),
            QStringLiteral("%1失败：命令执行超时。").arg(operationText));
        return false;
    }
    if (result.exitCode != 0)
    {
        // privilegePromptHandled：权限恢复提示已覆盖本次失败时不再显示通用命令错误框。
        const bool privilegePromptHandled = ks::ui::promptForPrivilegeFailure(
            this,
            operationText,
            result.mergedOutputText);
        if (!privilegePromptHandled)
        {
            QMessageBox::warning(
                this,
                QStringLiteral("引导编辑器"),
                QStringLiteral("%1失败：\n%2").arg(operationText, result.mergedOutputText.trimmed()));
        }
        return false;
    }

    if (showSuccessToast)
    {
        QMessageBox::information(this, QStringLiteral("引导编辑器"), QStringLiteral("%1成功。").arg(operationText));
    }
    return true;
}

bool BootEditorTab::applyBootMenuPolicyByIdentifier(
    const QString& identifierText,
    const QString& policyValueText,
    const QString& operationText)
{
    // 公共策略写入：
    // - 统一校验标识符与目标策略参数；
    // - 成功后给出明确结果提示。
    const QString normalizedIdentifierText = identifierText.trimmed();
    const QString normalizedPolicyText = policyValueText.trimmed();
    if (normalizedIdentifierText.isEmpty() || normalizedPolicyText.isEmpty())
    {
        QMessageBox::warning(
            this,
            QStringLiteral("传统引导"),
            QStringLiteral("参数无效：标识符或策略为空。"));
        return false;
    }

    if (!runBcdAndExpectSuccess(
        QStringList{
            QStringLiteral("/set"),
            normalizedIdentifierText,
            QStringLiteral("bootmenupolicy"),
            normalizedPolicyText
        },
        operationText,
        false))
    {
        return false;
    }

    QMessageBox::information(
        this,
        QStringLiteral("传统引导"),
        QStringLiteral("%1成功。\n标识符：%2\n策略：%3")
        .arg(operationText)
        .arg(normalizedIdentifierText)
        .arg(normalizedPolicyText));
    return true;
}

QString BootEditorTab::normalizeElementKey(const QString& rawKeyText)
{
    // 规范化规则：
    // - 转小写；
    // - 去除空格、连字符、下划线与制表符；
    // - 保留英数字与常见中文字段名。
    QString normalizedText = rawKeyText.trimmed().toLower();
    normalizedText.remove(QRegularExpression(QStringLiteral("[\\s\\-_:]")));
    return normalizedText;
}

std::vector<BootEditorTab::BcdEntry> BootEditorTab::parseBcdEnumOutput(const QString& enumOutputText)
{
    std::vector<BcdEntry> entryList;

    BcdEntry currentEntry;
    QStringList currentRawLineList;
    bool insideBlock = false;
    bool nextNonEmptyLineIsType = false;

    // flushCurrent：
    // - 将当前构建中的对象推入结果；
    // - 清理状态以便开始下一对象。
    const auto flushCurrent = [&entryList, &currentEntry, &currentRawLineList]()
        {
            if (currentEntry.identifierText.trimmed().isEmpty()
                && currentEntry.elementMap.isEmpty()
                && currentEntry.objectTypeText.trimmed().isEmpty())
            {
                currentRawLineList.clear();
                currentEntry = BcdEntry();
                return;
            }

            const QString idLowerText = currentEntry.identifierText.trimmed().toLower();
            currentEntry.isBootManager = (idLowerText == QStringLiteral("{bootmgr}"));
            currentEntry.isCurrent = (idLowerText == QStringLiteral("{current}"));
            currentEntry.rawBlockText = currentRawLineList.join('\n');
            entryList.push_back(currentEntry);

            currentEntry = BcdEntry();
            currentRawLineList.clear();
        };

    const QStringList allLineList = enumOutputText.split('\n');
    const QRegularExpression separatorRegex(QStringLiteral("^-{3,}$"));
    const QRegularExpression pairRegex(QStringLiteral("^(.+?)\\s{2,}(.+)$"));

    for (const QString& rawLine : allLineList)
    {
        const QString lineText = rawLine;
        const QString trimmedLineText = lineText.trimmed();

        if (trimmedLineText.isEmpty())
        {
            if (insideBlock)
            {
                currentRawLineList.push_back(lineText);
            }
            continue;
        }

        if (separatorRegex.match(trimmedLineText).hasMatch())
        {
            flushCurrent();
            insideBlock = true;
            nextNonEmptyLineIsType = true;
            currentRawLineList.push_back(lineText);
            continue;
        }

        if (!insideBlock)
        {
            continue;
        }

        currentRawLineList.push_back(lineText);

        if (nextNonEmptyLineIsType)
        {
            currentEntry.objectTypeText = trimmedLineText;
            nextNonEmptyLineIsType = false;
            continue;
        }

        const QRegularExpressionMatch pairMatch = pairRegex.match(lineText);
        if (!pairMatch.hasMatch())
        {
            continue;
        }

        const QString keyText = pairMatch.captured(1).trimmed();
        const QString valueText = pairMatch.captured(2).trimmed();
        const QString normalizedKeyText = normalizeElementKey(keyText);

        if (!normalizedKeyText.isEmpty())
        {
            currentEntry.elementMap.insert(normalizedKeyText, valueText);
        }

        const bool maybeIdentifierKey =
            normalizedKeyText.contains(QStringLiteral("identifier"))
            || normalizedKeyText.contains(QStringLiteral("标识符"))
            || normalizedKeyText.contains(QStringLiteral("识别符"));
        if (currentEntry.identifierText.trimmed().isEmpty())
        {
            if (maybeIdentifierKey)
            {
                currentEntry.identifierText = valueText;
            }
            else if (valueText.startsWith('{') && valueText.endsWith('}'))
            {
                currentEntry.identifierText = valueText;
            }
        }
    }

    flushCurrent();
    return entryList;
}

QString BootEditorTab::boolToBcdOnOff(const bool enabled)
{
    return enabled ? QStringLiteral("on") : QStringLiteral("off");
}

QString BootEditorTab::boolToBcdYesNo(const bool enabled)
{
    return enabled ? QStringLiteral("yes") : QStringLiteral("no");
}
