// SPDX-FileCopyrightText: 2022 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-or-later

// 项目自身文件
#include "DeviceStorage.h"
#include "commonfunction.h"
#include "commondefine.h"
#include <cfloat>
#include <cmath>

// Qt库文件
#include <QDir>
#include "DDLog.h"
// Qt库文件
#include<QLoggingCategory>
#include <QRegularExpression>
using namespace DDLog;

#define DISK_SCALE_1024 1024
#define DISK_SCALE_1000 1000

// MANFID: 十六进制字符串 -> 厂商名
static const QMap<QString, QString> MANFID_TABLE = {
    {"000001", "Panasonic"},
    {"000002", "Toshiba"},
    {"000003", "SanDisk"},
    {"00001b", "Samsung"},
    {"00001d", "ADATA"},
    {"000027", "Phison"},
    {"000028", "Lexar"},
    {"000031", "Silicon Power"},
    {"000041", "Kingston"},
    {"000074", "Transcend Information"},
    {"000076", "Patriot Memory"},
    {"000082", "Sony"},
    {"00009c", "Angelbird / Hoodman"}
};

// OEMID: 十六进制字符串 -> 厂商名
static const QMap<QString, QString> OEMID_TABLE = {
    {"3432", "Kingston"},
    {"4144", "ADATA"},
    {"4245", "Lexar / Angelbird / Hoodman"},
    {"4a45", "Transcend Information"},
    {"4a54", "Sony"},
    {"4a60", "Transcend Information"},
    {"5041", "Panasonic"},
    {"5048", "Phison"},
    {"5054", "SanDisk"},
    {"5344", "SanDisk"},
    {"534d", "Samsung"},
    {"534f", "Angelbird / Hoodman"},
    {"5350", "Silicon Power"},
    {"544d", "Toshiba"}
};

DeviceStorage::DeviceStorage()
    : DeviceBaseInfo()
    , m_Model("")
//    , m_Vendor("")
    , m_MediaType("")
    , m_Size("")
    , m_SizeBytes(0)
    , m_RotationRate("")
    , m_Interface("")
    , m_SerialNumber("")
    , m_Capabilities("")
    , m_KeyToLshw("")
    , m_KeyFromStorage("")
{
    qCDebug(appLog) << "DeviceStorage constructor";
    // 初始化可显示属性
    initFilterKey();
}

TomlFixMethod DeviceStorage::setInfoFromTomlOneByOne(const QMap<QString, QString> &mapInfo)
{
    qCDebug(appLog) << "DeviceStorage::setInfoFromTomlOneByOne";
    TomlFixMethod ret = TOML_None;
    // 添加基本信息
    setTomlAttribute(mapInfo, "Media Type", m_MediaType);
    setTomlAttribute(mapInfo, "Size", m_Size);
    setTomlAttribute(mapInfo, "Capabilities", m_Capabilities);
    // 添加其他信息,成员变量
    setTomlAttribute(mapInfo, "Firmware Version", m_FirmwareVersion);
    setTomlAttribute(mapInfo, "Speed", m_Speed);
    setTomlAttribute(mapInfo, "Serial Number", m_SerialNumber);
    setTomlAttribute(mapInfo, "Interface", m_Interface);
    ret = setTomlAttribute(mapInfo, "Rotation Rate", m_RotationRate);
    // 3. 获取设备的其它信息
    getOtherMapInfo(mapInfo);
    return ret;
}

static QString decimalkilos(quint64 value)
{
    qCDebug(appLog) << "decimalkilos";
    const QString prefixes("KMGTPEZY");
    int i = 0;
    quint64 curValue = value;
    QString valueStr = QString();
    while ((i < prefixes.size()) && ((curValue > 1000) || (curValue % 1000 == 0)))
    {
        value = curValue;
        curValue = curValue / 1000;
        i++;
    }

    if (i < 4) {
        qCDebug(appLog) << "decimalkilos, i < 4";
        quint64 diffValue = value - curValue * 1000;
        double calValue = diffValue / 1000.0 + 0.1;
        curValue += static_cast<quint64>(calValue);
        valueStr = QString::number(curValue) + " ";
        if (i > 0)
            valueStr += prefixes[i - 1];
    } else if (i <= prefixes.size()) { // 单位T以上处理
        qCDebug(appLog) << "decimalkilos, i <= prefixes.size()";
        if (value % 1000 >= 1)
            valueStr = QString::number(value) + " " + prefixes[i - 2]; //保留小数部分 如1920GB 10001GB
        else
            valueStr = QString::number(curValue) + " " + prefixes[i - 1]; //无小数部分入整 如1TB
    }
    valueStr += "B";
    return valueStr;
}

static quint64 convertToBytes(const QString& size, double scale)
{
    qCDebug(appLog) << "convertToBytes";
    /*convert "KB MB GB TB PB EB ZB YB " to bytes */
    const QString prefixes("KMGTPEZY");
    quint64 diskBytesSize = 0;
    double multiplier = 1;
    double diskSizeFloat = 0;

    QRegularExpression reg("([0-9]*\\.?[0-9]*)([A-Za-z]*)");
    QRegularExpressionMatch match = reg.match(size);
    if(!match.hasMatch()) {
        qCDebug(appLog) << "convertToBytes, no match";
        return diskBytesSize;
    }
    QString sizeValue1 = match.captured(1);
    if(sizeValue1.isEmpty()) {
        qCDebug(appLog) << "convertToBytes, sizeValue1 is empty";
        return diskBytesSize;
    }
    QString diskUnits = size.right(size.length() - sizeValue1.size()).trimmed().toUpper();
    if(diskUnits.isEmpty()) {
        qCDebug(appLog) << "convertToBytes, diskUnits is empty";
        return diskBytesSize;
    }
    diskUnits.replace("B","").replace("I","");
    QChar lastChar = diskUnits.at(diskUnits.length() - 1);

    if (prefixes.contains(diskUnits)) {
        qCDebug(appLog) << "convertToBytes, prefixes contains diskUnits";
        diskSizeFloat = sizeValue1.toDouble();

        int i = 0;
        while (i < prefixes.size()) {
            QChar iChar = prefixes.at(i++);
            if(iChar == lastChar) {
                qCDebug(appLog) << "convertToBytes, iChar == lastChar";
                multiplier = std::pow(scale,i);
                break;
            }
        }
    }
    diskBytesSize = static_cast<quint64>(diskSizeFloat * multiplier);
    return diskBytesSize;
}

void DeviceStorage::unitConvertByDecimal()
{
    qCDebug(appLog) << "DeviceStorage::unitConvertByDecimal";
    if(m_SizeBytes > 0)
        m_Size = decimalkilos(m_SizeBytes);
}

bool DeviceStorage::setHwinfoInfo(const QMap<QString, QString> &mapInfo)
{
    qCDebug(appLog) << "Set hwinfo info for storage device";
    // 龙芯机器中 hwinfo --disk会列出所有的分区信息
    // 存储设备不应包含分区，根据SysFS BusID 来确定是否是分区信息
    if (mapInfo.find("SysFS BusID") == mapInfo.end()) {
        qCDebug(appLog) << "Invalid hwinfo info - missing SysFS BusID";
        return false;
    }

    if (!Common::isHwPlatform()) {
        setAttribute(mapInfo, "Model", m_Name);
    }
    setAttribute(mapInfo, "Vendor", m_Vendor);

    // 希捷硬盘为ATA硬盘，无法直接获取厂商信息,只能特殊处理
    if (m_Name.startsWith("ST") && m_Vendor.isEmpty()) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, vendor is Seagate";
        m_Vendor = "ST";
    }
    //根据产品PN中的固定前两位 RS来匹配厂商 为Longsys 如产品PN ：RSYE3836N-480G    RSYE3836N-960G    RSYE3836N-1920     RSYE3836N-3840
    if (m_Name.startsWith("RS") && m_Vendor.isEmpty()) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, vendor is Longsys";
        m_Vendor = "Longsys";
    }

    setAttribute(mapInfo, "Driver", m_Driver); // 驱动
    QRegularExpression exp("pci 0x[0-9a-zA-Z]*");
    QRegularExpressionMatch match = exp.match(m_Vendor);
    if (match.hasMatch()) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, vendor is pci";
        m_Vendor = "";
    }

    if (mapInfo.contains("Driver Modules")) {
        if (mapInfo.value("Driver Modules").contains("usb_storage", Qt::CaseInsensitive)) {
            m_Interface = "USB";
        }
    }

    setAttribute(mapInfo, "Attached to", m_Interface);
    QRegularExpression re(".*\\((.*)\\).*");
    match = re.match(m_Interface);
    if (match.hasMatch()) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, interface has match";
        m_Interface = match.captured(1);
        m_Interface.replace("Controller", "");
        m_Interface.replace("controller", "");
    }

    setAttribute(mapInfo, "Revision", m_Version);
    setAttribute(mapInfo, "Hardware Class", m_Description);
    setAttribute(mapInfo, "Capacity", m_Size);

    // hwinfo里面显示的内容是  14 GB (15376000000 bytes) 需要处理
    QRegularExpression reSize(".*\\((.*)bytes\\).*");
    match = reSize.match(m_Size);
    if (match.hasMatch()) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, size has match";
        bool ok = false;
        quint64 bytesSize = match.captured(1).trimmed().toULongLong(&ok);
        if (ok) {
            qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, size convert to ullong success";
            m_Size = decimalkilos(bytesSize);
            m_SizeBytes = bytesSize;
        } else {
            qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, size convert to ullong failed";
            m_Size.replace(QRegularExpression("\\(.*\\)"), "").replace(" ", "");
            m_SizeBytes = convertToBytes(m_Size,DISK_SCALE_1024);
        }
    } else {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, size has no match";
        m_Size.replace(QRegularExpression("\\(.*\\)"), "").replace(" ", "");
        m_SizeBytes = convertToBytes(m_Size,DISK_SCALE_1024);
    }

    // 如果既没有capacity也没有序列号则认为该磁盘无效,否则都属于有效磁盘
    if ((m_Size.startsWith("0") || m_Size == "") && m_SerialNumber == "") {
        qCDebug(appLog) << "Invalid storage device - empty size and serial number";
        return false;
    }

    // get serial num
    m_SerialNumber = "";
    QString strLink = mapInfo["SysFS Device Link"];
    m_SerialNumber = getSerialID(strLink);
    if (m_SerialNumber.isEmpty()) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, serial number is empty";
        setAttribute(mapInfo, "Serial ID", m_SerialNumber);
    }
    if (m_SerialNumber.compare("0",Qt::CaseInsensitive) == 0) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, serial number is 0";
        m_SerialNumber = "";
    }

    setAttribute(mapInfo, "SysFS BusID", m_KeyToLshw);
    setAttribute(mapInfo, "Device File", m_DeviceFile);

    // 专有文件
    QString logicalName = ((QString)mapInfo["SysFS ID"]).replace("/class/block", "");

    QDir blockDir("/sys/block/");
    QStringList blockfs = blockDir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::Readable);
    foreach (QString fsname, blockfs) {
        if (m_DeviceFile.contains(fsname, Qt::CaseInsensitive)) {
            qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, device file contains fsname";
            logicalName = fsname;
            break;
        }
    }

    QString Path = "/sys/block/" + logicalName + "/device/spec_version";
    QFile file(Path);
    if (file.open(QIODevice::ReadOnly)) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, open spec_version success";
        QString output = file.readAll();
        if (!output.isEmpty()) {
            m_Interface = "UFS";
        }
        file.close();
    }

    if (m_KeyToLshw.contains("nvme", Qt::CaseInsensitive)) {
        qCDebug(appLog) << "DeviceStorage::setHwinfoInfo, key contains nvme";
        setAttribute(mapInfo, "SysFS Device Link", m_NvmeKey);
    }

    setAttribute(mapInfo, "Module Alias", m_Modalias);
    setAttribute(mapInfo, "VID_PID", m_VID_PID);
    m_PhysID = m_VID_PID;

    if (m_Driver.contains("mmcblk")) {
        QString sysfsDeviceLink = mapInfo.value("SysFS Device Link");

        if (!sysfsDeviceLink.isEmpty())
        {
            if (!sysfsDeviceLink.startsWith("/sys/"))
            {
                sysfsDeviceLink = "/sys" + sysfsDeviceLink;
            }

            QString err;
            QString name = Common::safeReadSysFsFile(sysfsDeviceLink, "name", err);
            if (err.isEmpty())
                m_Name = name;

            QString manfIdRaw = Common::safeReadSysFsFile(sysfsDeviceLink, "manfid", err);
            if (err.isEmpty()) {
                m_Vendor = getManfName(manfIdRaw);
            }

            QString oemIdRaw = Common::safeReadSysFsFile(sysfsDeviceLink, "oemid", err);
            if (err.isEmpty()) {
                if (m_Vendor.isEmpty()) {
                    m_Vendor = getOemName(oemIdRaw);
                }
            }
        }
    }

    getOtherMapInfo(mapInfo);
    return true;
}

QString DeviceStorage::getSerialID(QString &strDeviceLink)
{
    qCDebug(appLog) << "DeviceStorage::getSerialID";
    //取SerialID优先级：1.取cid 2.取unique_number 3.取hwinfo中的SerialID
    QString strSerialNumber = "";
    if (!strDeviceLink.isEmpty() && strDeviceLink.contains("platform/")) {
        qCDebug(appLog) << "DeviceStorage::getSerialID, device link contains platform";
        // /devices/platform/f8300000.ufs/host0/target0:0:0/0:0:0:3
        // /proc/bootdevice/name:f8300000.ufs
         QRegularExpression reg(".*platform/([^/]+)/.*");
         QString strName = "";
         QString strBootdeviceName = "";
         QRegularExpressionMatch match = reg.match(strDeviceLink);
         if (match.hasMatch()) {
             strName = match.captured(1);
         }
        if (!strName.isEmpty()) { //取到设备名称再去读文件，因为读文件开销大。
            qCDebug(appLog) << "DeviceStorage::getSerialID, strName is not empty";
            QString Path = "/proc/bootdevice/name";
            QFile file(Path);
            if (file.open(QIODevice::ReadOnly)) {
                qCDebug(appLog) << "DeviceStorage::getSerialID, open /proc/bootdevice/name success";
                strBootdeviceName = file.readAll();
                file.close();
            }
            if (strName == strBootdeviceName) {
                qCDebug(appLog) << "DeviceStorage::getSerialID, strName == strBootdeviceName";
                Path = "/proc/bootdevice/cid";
                QFile filecid(Path);
                if (filecid.open(QIODevice::ReadOnly)) {
                    qCDebug(appLog) << "DeviceStorage::getSerialID, open /proc/bootdevice/cid success";
                    strSerialNumber = filecid.readAll().trimmed();
                    filecid.close();
                }
            }
        }
    }

    if (strSerialNumber.isEmpty()) {
        qCDebug(appLog) << "DeviceStorage::getSerialID, serial number is empty";
        QString Path = "/sys" + strDeviceLink + "/unique_number";
        QFile file(Path);
        if (file.open(QIODevice::ReadOnly)) {
            qCDebug(appLog) << "DeviceStorage::getSerialID, open unique_number success";
            QString value = file.readAll();
            strSerialNumber = value;
            file.close();
        }
    }
    return strSerialNumber;
}

const QString &DeviceStorage::mediaType() const
{
    return m_MediaType;
}

const QString &DeviceStorage::interface() const
{
    return m_Interface;
}

bool DeviceStorage::addInfoFromlshw(const QMap<QString, QString> &mapInfo)
{
    qCDebug(appLog) << "Add lshw info for storage device";
    // 先获取需要进行匹配的关键字
    QStringList keys = mapInfo["bus info"].split("@");
    if (keys.size() != 2) {
        qCDebug(appLog) << "Invalid lshw info - malformed bus info";
        return false;
    }

    QString key = keys[1].trimmed();
    key.replace(".", ":");

    if (key != m_KeyToLshw) {
        qCDebug(appLog) << "Key mismatch - expected:" << m_KeyToLshw << "got:" << key;
        return false;
    }

    // 获取唯一key
    QStringList words = mapInfo["bus info"].split(":");
    if (words.size() == 2) {
        qCDebug(appLog) << "DeviceStorage::addInfoFromlshw, words size is 2";
        m_KeyFromStorage = words[0];
        m_KeyFromStorage.replace("@", "");
    }

    // 更新接口
    setAttribute(mapInfo, "interface", m_Interface, false);

    // 获取基本信息
    getInfoFromLshw(mapInfo);

    // 获取其它设备信息
    getOtherMapInfo(mapInfo);

    return true;
}

bool DeviceStorage::addNVMEInfoFromlshw(const QMap<QString, QString> &mapInfo)
{
    qCDebug(appLog) << "DeviceStorage::addNVMEInfoFromlshw";
    QStringList keys = mapInfo["bus info"].split("@");
    if (keys.size() != 2)
        return false;

    QString key = keys[1].trimmed();

    // SysFS Device Link: /devices/pci0000:00/0000:00:05.0/0000:0d:00.0/nvme/nvme0
    //bus info: pci@0000:0d:00.0
    // 确认为同一设备
    if (m_NvmeKey.contains(key, Qt::CaseInsensitive)) {
        qCDebug(appLog) << "DeviceStorage::addNVMEInfoFromlshw, key contains nvme";
        setAttribute(mapInfo, "vendor", m_Vendor);
    } else {
        qCDebug(appLog) << "DeviceStorage::addNVMEInfoFromlshw, key not contains nvme";
        return false;
    }

    return true;
}

bool DeviceStorage::addInfoFromSmartctl(const QString &name, const QMap<QString, QString> &mapInfo)
{
    qCDebug(appLog) << "DeviceStorage::addInfoFromSmartctl";
    // 查看传入的设备信息与当前的设备信息是不是同一个设备信息
    if (!m_DeviceFile.contains(name, Qt::CaseInsensitive))
        return false;

    // 获取基本信息
    getInfoFromsmartctl(mapInfo);
    return true;
}

bool DeviceStorage::setMediaType(const QString &name, const QString &value)
{
    qCDebug(appLog) << "DeviceStorage::setMediaType";
    if (!m_DeviceFile.contains(name)) {
        qCDebug(appLog) << "DeviceStorage::setMediaType, device file does not contain name";
        return false;
    }

    if (QString("0") == value) {
        qCDebug(appLog) << "DeviceStorage::setMediaType, media type is SSD";
        m_MediaType = "SSD";
    } else if (QString("1") == value) {
        qCDebug(appLog) << "DeviceStorage::setMediaType, media type is HDD";
        m_MediaType = "HDD";
    } else {
        qCDebug(appLog) << "DeviceStorage::setMediaType, media type is Unknown";
        m_MediaType = "Unknown";
    }

    return true;
}

bool DeviceStorage::isValid()
{
    qCDebug(appLog) << "DeviceStorage::isValid";
    // 若是m_Size为空则 该设备无效
    if (m_Size.isEmpty() && m_SizeBytes == 0) {
        qCDebug(appLog) << "Storage device invalid - empty size";
        return false;
    }

    return true;
}

void DeviceStorage::setDiskSerialID(const QString &deviceFiles)
{
    qCDebug(appLog) << "DeviceStorage::setDiskSerialID";
    // Serial ID 与 device Files 中信息一致
    if (!m_SerialNumber.isEmpty() && deviceFiles.contains(m_SerialNumber))
        return;

    QStringList itemList = deviceFiles.split(",");

    QString modelName = m_Name;
    modelName.replace(" ", "_");

    foreach (auto item, itemList) {
        if (item.contains("by-id", Qt::CaseInsensitive) &&
                item.contains(modelName, Qt::CaseInsensitive)) {
            qCDebug(appLog) << "DeviceStorage::setDiskSerialID, item contains by-id and modelName";

            int index;
            index = item.lastIndexOf("_");
            item = item.mid(index + 1);
            item.replace(QRegularExpression("-[\\s\\S]*$"), "");
            m_SerialNumber = item;
            break;
        }
    }
}

QString DeviceStorage::getDiskSerialID()
{
    qCDebug(appLog) << "DeviceStorage::getDiskSerialID";
    if (m_Interface.contains("USB", Qt::CaseInsensitive)) {
        qCDebug(appLog) << "DeviceStorage::getDiskSerialID, interface contains USB";
        return m_SerialNumber + m_KeyToLshw;
    }
    return m_SerialNumber;
}

void DeviceStorage::appendDisk(DeviceStorage *device)
{
    qCDebug(appLog) << "DeviceStorage::appendDisk";
    QList<QPair<QString, QString> > allAttribs = device->getBaseAttribs();
    QMap<QString, QString> allAttribMaps;
    for (int i = 0; i < allAttribs.size(); ++i) {
        allAttribMaps.insert(allAttribs[i].first, allAttribs[i].second);
    }

    quint64 size2 = device->getDiskSizeByte();
    if (m_SizeBytes == 0) {
        qCDebug(appLog) << "DeviceStorage::appendDisk, m_SizeBytes is 0";
        m_SizeBytes = size2;
    } else if (size2 > 0) {
        qCDebug(appLog) << "DeviceStorage::appendDisk, size2 > 0";
        m_SizeBytes += size2;

        QList<QPair<QString, QString> > allOtherAttribs = device->getOtherAttribs();
        QMap<QString, QString> allOtherAttribMaps;
        for (int i = 0; i < allOtherAttribs.size(); ++i) {
            allAttribMaps.insert(allOtherAttribs[i].first, allOtherAttribs[i].second);
        }

        loadOtherDeviceInfo();
        //合并
        QMap<QString, QString> curAllOtherAttribMaps;
        for (int i = 0; i < m_LstOtherInfo.size(); ++i) {
            curAllOtherAttribMaps.insert(m_LstOtherInfo[i].first, m_LstOtherInfo[i].second);
        }

        QStringList keyList;
        keyList.append(translateStr("bus info"));
        keyList.append(translateStr("Device File"));
        keyList.append(translateStr("Device Number"));
        keyList.append(translateStr("logical name"));
        for (QString keyStr : keyList) {
            QString curBusInfo = curAllOtherAttribMaps[keyStr];
            QString busInfo = allAttribMaps[keyStr];
            if (!curBusInfo.isEmpty() && !busInfo.isEmpty() && curBusInfo != busInfo) {
                // qCDebug(appLog) << "DeviceStorage::appendDisk, bus info not empty and not equal";
                setOtherDeviceInfo(keyStr, curBusInfo + "," + busInfo);
            }
        }
        loadOtherDeviceInfo();
    }
}

void DeviceStorage::checkDiskSize()
{
    qCDebug(appLog) << "DeviceStorage::checkDiskSize";
    if (!Common::isHwPlatform()) {
        return; //定制机型专用，其它慎用
    }
    quint64 gbyte =  1000000000;

//    if (m_Interface.contains("UFS", Qt::CaseInsensitive)) { // TODO Ignore ufs disk
    if (m_SizeBytes > 255*gbyte && m_SizeBytes < 257*gbyte) {
        m_Size = "256 GB";
    } else if (m_SizeBytes > 511*gbyte && m_SizeBytes < 513*gbyte) {
        m_Size = "512 GB";
    } else if (m_SizeBytes > 999*gbyte && m_SizeBytes < 1025*gbyte) {
        m_Size = "1 TB";
    } else if (m_SizeBytes > 1999*gbyte && m_SizeBytes < 2049*gbyte) {
        m_Size = "2 TB";
    }
//    }
    if (m_Interface.contains("USB", Qt::CaseInsensitive)) {
        if (m_SizeBytes > 15*gbyte && m_SizeBytes < 17*gbyte) {
            m_Size = "16 GB";
        } else if (m_SizeBytes > 31*gbyte && m_SizeBytes < 33*gbyte) {
            m_Size = "32 GB";
        } else if (m_SizeBytes > 63*gbyte && m_SizeBytes < 65*gbyte) {
            m_Size = "64 GB";
        } else if (m_SizeBytes > 127*gbyte && m_SizeBytes < 129*gbyte) {
            m_Size = "128 GB";
        }
    }
}

QString DeviceStorage::compareSize(const QString &size1, const QString &size2)
{
    qCDebug(appLog) << "DeviceStorage::compareSize";
    // 比较smartctl中可能提供的两个大小，取大值作为存储设备的大小
    if (size1.isEmpty() || size2.isEmpty())
        return size1 + size2;

    // 提取原始字节数（方括号前的数字，千分位逗号/点）比较
    // zh_CN: "Total NVM Capacity:  1,024,209,543,168 [1.02 TB]"
    // de_DE: "Total NVM Capacity:  1.024.209.543.168 [1,02 TB]"
    // 格式2: "Total NVM Capacity:  240,057,409,536 bytes [240 GB]"
    auto extractBytes = [](const QString &str) -> quint64 {
        QRegularExpression reg("(\\d[\\d,.]*)\\s*(?:bytes\\s*)?\\[");
        QRegularExpressionMatch match = reg.match(str);
        if (match.hasMatch()) {
            QString raw = match.captured(1);
            raw.remove(",");
            raw.remove(".");
            return raw.toULongLong();
        }
        return 0;
    };

    quint64 bytes1 = extractBytes(size1);
    quint64 bytes2 = extractBytes(size2);

    // 返回较大值
    if (bytes1 > bytes2) {
        qCDebug(appLog) << "DeviceStorage::compareSize, bytes1 > bytes2";
        return size1;
    } else {
        qCDebug(appLog) << "DeviceStorage::compareSize, bytes1 <= bytes2";
        return size2;
    }
}

const QString &DeviceStorage::name() const
{
    // qCDebug(appLog) << "DeviceStorage::name";
    return m_Name;
}

const QString &DeviceStorage::vendor() const
{
    // qCDebug(appLog) << "DeviceStorage::vendor";
    return m_Vendor;
}

const QString &DeviceStorage::driver() const
{
    // qCDebug(appLog) << "DeviceStorage::driver";
    return m_Driver;
}

const QString &DeviceStorage::keyFromStorage()const
{
    // qCDebug(appLog) << "DeviceStorage::keyFromStorage";
    return m_KeyFromStorage;
}

QString DeviceStorage::subTitle()
{
    // qCDebug(appLog) << "DeviceStorage::subTitle";
    return m_Name;
}

const QString DeviceStorage::getOverviewInfo()
{
    // qCDebug(appLog) << "DeviceStorage::getOverviewInfo";
    QString overViewInfo;

    if (m_Interface.contains("UFS", Qt::CaseInsensitive)) {
        overViewInfo = QString("%1 %2").arg(m_Size).arg("UFS");
    } else if (m_Interface.contains("USB", Qt::CaseInsensitive)) {
        overViewInfo = QString("%1 %2").arg(m_Size).arg("USB");
    } else {
        overViewInfo = QString("%1 %2").arg(m_Size).arg(m_MediaType);
    }

    return overViewInfo;
}

void DeviceStorage::initFilterKey()
{
    qCDebug(appLog) << "DeviceStorage::initFilterKey";
    // hwinfo --disk
    addFilterKey("Hardware Class");
    addFilterKey("Device File");
    addFilterKey("ansiversion");
    addFilterKey("bus info");
    addFilterKey("logical name");
    addFilterKey("logicalsectorsize");
    // addFilterKey("physical id"));
    addFilterKey("sectorsize");
    addFilterKey("guid");
    addFilterKey("Config Status");
    addFilterKey("Device Number");
    addFilterKey("Geometry (Logical)");

}

void DeviceStorage::loadBaseDeviceInfo()
{
    qCDebug(appLog) << "DeviceStorage::loadBaseDeviceInfo";
    // 添加基本信息
    addBaseDeviceInfo("Name", m_Name);
    if (!Common::isHwPlatform()) {
        addBaseDeviceInfo(("Vendor"), m_Vendor);
    }
    addBaseDeviceInfo("Media Type", translateStr(m_MediaType));
    addBaseDeviceInfo("Size", m_Size);
    addBaseDeviceInfo("Version", m_Version);
    addBaseDeviceInfo("Capabilities", m_Capabilities);
}

void DeviceStorage::loadOtherDeviceInfo()
{
    qCDebug(appLog) << "DeviceStorage::loadOtherDeviceInfo";
    // 添加其他信息,成员变量
    addOtherDeviceInfo("Firmware Version", m_FirmwareVersion);
    addOtherDeviceInfo("Speed", m_Speed);
    addOtherDeviceInfo("Description", m_Description);

    for(int i = 0 ; i < m_SerialNumber.count(); i++) {
        QChar cha = m_SerialNumber.at(i);
        ushort uni = cha.unicode();
        if(uni < 33 || uni > 126) {
            qCWarning(appLog)<<"smartctl Serial number is not LetterOrNumber "<< m_SerialNumber;
            m_SerialNumber.clear();
            break;
        }
    }

    addOtherDeviceInfo("Serial Number", m_SerialNumber);
    addOtherDeviceInfo("Interface", m_Interface);
    addOtherDeviceInfo("Rotation Rate", m_RotationRate);
    addOtherDeviceInfo("Module Alias", m_Modalias);
    addOtherDeviceInfo("Physical ID", m_PhysID);

    if (m_RotationRate == QString("Solid State Device")) {
        qCDebug(appLog) << "DeviceStorage::loadOtherDeviceInfo, rotation rate is Solid State Device";
        m_MediaType = "SSD";
    }

    // 将QMap<QString, QString>内容转存为QList<QPair<QString, QString>>
    mapInfoToList();
}

void DeviceStorage::loadTableHeader()
{
    qCDebug(appLog) << "DeviceStorage::loadTableHeader";
    // 加载表头信息
    m_TableHeader.append("Name");
    m_TableHeader.append("Vendor");
    m_TableHeader.append("Media Type");
    m_TableHeader.append("Size");
}

void DeviceStorage::loadTableData()
{
    qCDebug(appLog) << "DeviceStorage::loadTableData";
    // 加载表格数据
    QString model = m_Name;
    if (!available()) {
        qCDebug(appLog) << "DeviceStorage::loadTableData, not available";
        model = "(Unavailable) " + m_Name;
    }
    m_TableData.append(model);
    m_TableData.append(m_Vendor);
    m_TableData.append(translateStr(m_MediaType));
    m_TableData.append(m_Size);
}

void DeviceStorage::getInfoFromLshw(const QMap<QString, QString> &mapInfo)
{
    qCDebug(appLog) << "DeviceStorage::getInfoFromLshw";
    // lshw信息获取
    setAttribute(mapInfo, "capabilities", m_Capabilities);
    setAttribute(mapInfo, "version", m_Version);
    setAttribute(mapInfo, "serial", m_SerialNumber, false);
    setAttribute(mapInfo, "product", m_Name);
    setAttribute(mapInfo, "description", m_Description);
    QString sizeFromlshw = QString();
    quint64 sizeByte = 0;
    setAttribute(mapInfo, "size", sizeFromlshw, true);
    // 样式数据 223GiB (240GB) size: 57GiB (61GB)  size: 931GiB (1TB)
    QRegularExpression re(".*\\((.*)\\)$");
    QRegularExpressionMatch match = re.match(sizeFromlshw);
    if (match.hasMatch()) {
        qCDebug(appLog) << "DeviceStorage::getInfoFromLshw, size has match";
        sizeFromlshw = match.captured(1);
        sizeByte = convertToBytes(sizeFromlshw, DISK_SCALE_1000);
    }
    if (m_SizeBytes == 0)
        m_SizeBytes = sizeByte;

    if (m_Size.isEmpty())
        m_Size = sizeFromlshw;

    if (m_SerialNumber.compare("0", Qt::CaseInsensitive) == 0)
        m_SerialNumber = "";
}

void DeviceStorage::getInfoFromsmartctl(const QMap<QString, QString> &mapInfo)
{
    qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl";
    if (mapInfo.size() < 5) {
        if (!mapInfo.isEmpty() && m_Interface.contains("USB", Qt::CaseInsensitive)) {
            qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, mapInfo is not empty and interface contains USB";
            m_MediaType = "SSD";
        }
        return;
    }
    // 固件版本
    m_FirmwareVersion = mapInfo["Firmware Version"];

    // 速度
    QString sataVersion = mapInfo["SATA Version is"];
    QStringList strList = sataVersion.split(",");
    if (strList.size() == 2) {
        qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, strList size is 2";
        m_Speed = strList[1];
    }

    setAttribute(mapInfo, "Rotation Rate", m_RotationRate);
    // 解决Bug45428,INTEL SSDSA2BW160G3L 这个型号的硬盘通过lsblk获取的rota是１，所以这里需要特殊处理
    if (m_RotationRate == QString("Solid State Device")) {
        m_MediaType = "SSD";
        m_RotationRate = "";
    }

    // 安装大小
    QString capacity = mapInfo["User Capacity"];
    if (capacity == "")
        capacity = compareSize(mapInfo["Total NVM Capacity"], mapInfo["Namespace 1 Size/Capacity"]);

    if (capacity != "") {
        qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, capacity is not empty";
        QRegularExpression reg(".*\\[(.*)\\]$");
        QRegularExpressionMatch sizeMatch = reg.match(capacity);
        if (sizeMatch.hasMatch())
            m_Size = sizeMatch.captured(1);

        capacity.replace(",","").replace(" ","");
        QRegularExpression re("(\\d+)bytes*");     //取值格式如： User Capacity:    1,000,204,886,016 bytes [1.00 TB]     Total NVM Capacity:   256,060,514,304 [256 GB]
        int pos = re.match(capacity).capturedStart();
        if (pos != -1) {
            qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, capacity has match";
            QRegularExpressionMatch byteMatch = re.match(capacity);
            QString byteSize = byteMatch.captured(1);
            bool isValue = false;
            quint64 value = byteSize.trimmed().toULongLong(&isValue);
            if (value > 0 && isValue)
                m_SizeBytes = value;
        }
    }

    // 通过不断适配，当厂商有在固件中提供时，硬盘型号从smartctl中获取更加合理
    // 因为hwinfo获取的是主控的型号，而硬盘厂商由于还不能自己生产主控，只能采购别人的主控
    //SATA
    if (mapInfo.find("Device Model") != mapInfo.end()) {
        qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, mapInfo contains Device Model";
        m_Name = mapInfo["Device Model"];
    }
    //NVME
    if (mapInfo.find("Model Number") != mapInfo.end()) {
        qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, mapInfo contains Model Number";
        m_Name = mapInfo["Model Number"];
    }

    if (mapInfo.find("Serial Number") != mapInfo.end()) {
        qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, mapInfo contains Serial Number";
        setAttribute(mapInfo, "Serial Number", m_SerialNumber, true);
    } else if (mapInfo.find("Serial number") != mapInfo.end()) {
        qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, mapInfo contains Serial number";
        setAttribute(mapInfo, "Serial number", m_SerialNumber, true);
    }

    // 修正数值
    if(Common::boardVendorType() != "KLVV" && Common::boardVendorType() != "KLVU" \
        && Common::boardVendorType() != "PGUW" && Common::boardVendorType() != "PGUV")
            m_Size.replace(QRegularExpression("\\.0[1-9]"), ".00");
    //根据产品PN中的固定前两位 RS来匹配厂商 为Longsys 如产品PN ：RSYE3836N-480G    RSYE3836N-960G    RSYE3836N-1920     RSYE3836N-3840
    if (m_Name.startsWith("RS") && m_Vendor.isEmpty()) {
        qCDebug(appLog) << "DeviceStorage::getInfoFromsmartctl, name starts with RS and vendor is empty";
        m_Vendor = "Longsys";
    }
}

// 通过manfid获取厂商名称
QString DeviceStorage::getManfName(const QString &rawManfId)
{
    QString cleanId = rawManfId.trimmed().toLower();
    cleanId.remove("0x"); // 去除0x前缀
    return MANFID_TABLE.value(cleanId, rawManfId);
}

// 通过oemid获取厂商名称
QString DeviceStorage::getOemName(const QString &rawOemId)
{
    QString cleanId = rawOemId.trimmed().toLower();
    cleanId.remove("0x");
    return OEMID_TABLE.value(cleanId, rawOemId);
}
