/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2026-2026. All rights reserved.
 * ubs-engine is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

#include "ubse_urma_controller_api.h"
#include <netinet/in.h>
#include <securec.h>
#include "ubse_api_server_module.h"
#include "ubse_com_module.h"
#include "ubse_conf.h"
#include "ubse_context.h"
#include "ubse_election.h"
#include "ubse_logger.h"
#include "ubse_pack_util.h"
#include "ubse_serial_util.h"
#include "ubse_urma_controller.h"
#include "ubse_urma_controller_qos.h"

namespace ubse::urmaController {
using namespace ubse::common::def;
using namespace ubse::context;
using namespace api::server;
using namespace ubse::log;
using namespace ubse::utils;
using namespace ubse::election;
using namespace ubse::com;
using namespace ubse::serial;
using namespace ubse::config;
using namespace ubse::urma;

UBSE_DEFINE_THIS_MODULE("ubse");

const uint32_t UBSE_URMA_NAME_MAX = 32;        // 包含结束符长度
const uint32_t UBSE_MAX_URMA_PATH_LENGTH = 64; // 包含结束符长度
const size_t MAX_BUFFER_SIZE = 10 * 1024;      // 10 KB
const std::string URMA_PERMISSION = "urma";

bool IsUrmaApiSupported()
{
    if (UbseIsUrmaSupported()) {
        return true;
    }
    UBSE_LOG_WARN << "URMA feature is unsupported.";
    return false;
}

size_t UbseStringCalcSize(const std::string& str, size_t maxLen)
{
    size_t len = 0;
    len += sizeof(uint32_t); // 字符串长度指示
    len += std::min(maxLen, str.size());
    return len;
}

UbseResult LocalDevPack(std::vector<std::string>& nameInfos, std::vector<uint32_t> status,
                        std::vector<uint64_t>& hwResIds, UbseIpcMessage& response)
{
    if (nameInfos.size() != status.size() || status.size() != hwResIds.size()) {
        UBSE_LOG_ERROR << "nameInfos, status and hwResIds size mismatch";
        return UBSE_ERROR_INVAL;
    }
    size_t infoSize = nameInfos.size();
    size_t rspSize = sizeof(uint32_t);
    for (auto& s : nameInfos) {
        // 每个名字后面需要增加一个status占用4个字节
        rspSize += UbseStringCalcSize(s, UBSE_URMA_NAME_MAX - 1) + sizeof(uint32_t) + sizeof(uint64_t);
    }
    response.buffer = new (std::nothrow) uint8_t[rspSize];
    response.length = rspSize;
    if (response.buffer == nullptr) {
        UBSE_LOG_ERROR << "Failed to allocate response buffer for size=" << rspSize;
        return UBSE_ERROR_SERIALIZE_FAILED;
    }
    UbsePackUtil packUtil(response.buffer, response.length);
    if (!packUtil.UbsePackUint32(static_cast<uint32_t>(infoSize))) {
        UBSE_LOG_ERROR << "Failed to pack infoSize=" << infoSize;
        return UBSE_ERROR_SERIALIZE_FAILED;
    }

    for (size_t i = 0; i < nameInfos.size(); i++) {
        if (!packUtil.UbsePackString(nameInfos[i], UBSE_URMA_NAME_MAX - 1)) {
            UBSE_LOG_ERROR << "Failed to pack nameInfo[" << i << "]=" << nameInfos[i];
            return UBSE_ERROR_SERIALIZE_FAILED;
        }
        if (!packUtil.UbsePackUint32(status[i])) {
            UBSE_LOG_ERROR << "Failed to pack status[" << i << "]=" << status[i];
            return UBSE_ERROR_SERIALIZE_FAILED;
        }
        if (!packUtil.UbsePackUint64(hwResIds[i])) {
            UBSE_LOG_ERROR << "Failed to pack hwResIds[" << i << "]=" << hwResIds[i];
            return UBSE_ERROR_SERIALIZE_FAILED;
        }
    }
    return UBSE_OK;
}

UbseResult QosGetPack(std::vector<EtsQosConfig>& configs, UbseIpcMessage& response)
{
    uint32_t itemCount = static_cast<uint32_t>(configs.size());
    size_t rspSize = sizeof(uint32_t) + itemCount * (sizeof(uint32_t) + sizeof(uint32_t));

    response.buffer = new (std::nothrow) uint8_t[rspSize];
    response.length = rspSize;
    if (response.buffer == nullptr) {
        UBSE_LOG_ERROR << "Failed to allocate response buffer for size=" << rspSize;
        return UBSE_ERROR_SERIALIZE_FAILED;
    }

    UbsePackUtil packUtil(response.buffer, response.length);
    if (!packUtil.UbsePackUint32(itemCount)) {
        UBSE_LOG_ERROR << "Failed to pack itemCount=" << itemCount;
        delete[] response.buffer;
        response.buffer = nullptr;
        return UBSE_ERROR_SERIALIZE_FAILED;
    }

    for (const auto& config : configs) {
        uint32_t priorityValue = static_cast<uint32_t>(config.priority);
        uint32_t bandwidthGbps = config.bandwidth / NO_1000;
        if (!packUtil.UbsePackUint32(priorityValue) || !packUtil.UbsePackUint32(bandwidthGbps)) {
            UBSE_LOG_ERROR << "Failed to pack qos config";
            delete[] response.buffer;
            response.buffer = nullptr;
            return UBSE_ERROR_SERIALIZE_FAILED;
        }
    }
    return UBSE_OK;
}

UbseResult UbseUrmaControllerApi::Register()
{
    auto ubse_api_server_module = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (ubse_api_server_module == nullptr) {
        UBSE_LOG_ERROR << "Get api server module  failed";
        return UBSE_ERROR_NULLPTR;
    }
    auto ret = ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_CLI_DEV_GET, UbseUrmaDevGetByFilter);
    ret |=
        ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_DEV_ALLOC, UbseUrmaDevAlloc, URMA_PERMISSION);
    ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_DEV_FREE, UbseUrmaDevFree, URMA_PERMISSION);
    ret |=
        ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_DEV_GET, UbseUrmaDevGetLocal, URMA_PERMISSION);
    ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_QOS_CREATE, UbseUrmaQosCreateNative,
                                                      URMA_PERMISSION);
    ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_QOS_GET, UbseUrmaQosQueryNative,
                                                      URMA_PERMISSION);
    ret |=
        ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_QOS_DELETE, UbseUrmaQosDelete, URMA_PERMISSION);
    ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_CLI_QOS_CREATE, UbseUrmaQosCreateStream);
    ret |= ubse_api_server_module->RegisterIpcHandler(UBSE_URMA, UBSE_URMA_CLI_QOS_GET, UbseUrmaQosQueryStream);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "Registration of Urma Controller-API failed," << FormatRetCode(ret);
        return ret;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaQosCreateStream(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    if (req.buffer == nullptr) {
        UBSE_LOG_ERROR << "UbseUrmaQosCreateStream request info is null.";
        return UBSE_ERROR_NULLPTR;
    }

    UbseDeSerialization deserializer(req.buffer, req.length);
    uint32_t itemCount;
    deserializer >> itemCount;

    if (!deserializer.Check() || itemCount == NO_0 || itemCount > NO_2) {
        UBSE_LOG_ERROR << "Failed to deserialize request parameters, itemCount=" << itemCount;
        return UBSE_ERROR_DESERIALIZE_FAILED;
    }

    std::vector<EtsQosConfig> configs;
    configs.reserve(itemCount);
    for (uint32_t i = 0; i < itemCount; ++i) {
        EtsQosConfig config;
        uint32_t priorityValue;
        deserializer >> priorityValue >> config.bandwidth;
        config.bandwidth *= NO_1000;
        if (!deserializer.Check()) {
            UBSE_LOG_ERROR << "Failed to deserialize EtsQosConfig at index " << i;
            return UBSE_ERROR_DESERIALIZE_FAILED;
        }
        config.priority = static_cast<EtsPriority>(priorityValue);
        configs.push_back(std::move(config));
    }

    uint32_t ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosCreate(configs);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosCreate failed," << FormatRetCode(ret);
        return ret;
    }

    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        return UBSE_ERROR_NULLPTR;
    }
    UbseIpcMessage response = {nullptr, 0};
    ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaQosCreateStream response send failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaQosQueryStream(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    std::vector<EtsQosConfig> configs;
    auto ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosQuery(configs);
    if (ret != UBSE_OK && ret != UBSE_URMACONTRL_ERROR_ETS_TEMPLATE_NOT_APPLIED) {
        UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosGet failed," << FormatRetCode(ret);
        return ret;
    }

    UbseSerialization serializer;
    uint32_t itemCount = static_cast<uint32_t>(configs.size());
    serializer << itemCount;
    for (const auto& config : configs) {
        uint32_t priorityValue = static_cast<uint32_t>(config.priority);
        uint32_t bandwidthGbps = config.bandwidth / NO_1000;
        serializer << priorityValue << bandwidthGbps;
    }

    if (!serializer.Check()) {
        UBSE_LOG_ERROR << "Failed to serialize response";
        return UBSE_ERROR_SERIALIZE_FAILED;
    }

    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        return UBSE_ERROR_NULLPTR;
    }

    UbseIpcMessage response = {serializer.GetBuffer(), static_cast<uint32_t>(serializer.GetLength())};
    auto sendRet = apiServerModule->SendResponse(ret, context.requestId, response);
    if (sendRet != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaQosQueryStream response send failed," << FormatRetCode(sendRet);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaQosDelete(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    if (req.buffer != nullptr || req.length != 0) {
        UBSE_LOG_ERROR << "UbseUrmaQosDelete should not have request data.";
        return UBSE_ERR_INVALID_ARG;
    }

    uint32_t ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosDelete();
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosDelete failed," << FormatRetCode(ret);
        return ret;
    }

    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        return UBSE_ERROR_NULLPTR;
    }
    UbseIpcMessage response = {nullptr, 0};
    ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaQosDelete response send failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

uint32_t ParseUrmaDevGetRequest(const UbseIpcMessage& req, uint32_t& nodeId, std::vector<std::string>& deviceNameList)
{
    uint32_t deviceListSize;
    if (req.buffer == nullptr) {
        UBSE_LOG_ERROR << "Ubse Urma Dev Get IPC request buffer is null.";
        return UBSE_ERROR_NULLPTR;
    }
    UbseDeSerialization out{req.buffer, req.length};
    out >> nodeId >> deviceListSize;
    if (!out.Check() || deviceListSize > NO_1024) { // bonding设备数量不超过1024
        UBSE_LOG_ERROR << "Failed to deserialize basic parameters (nodeId, urmaType, deviceListSize), deviceListSize="
                       << deviceListSize;
        return UBSE_ERROR_DESERIALIZE_FAILED;
    }
    deviceNameList.clear();
    deviceNameList.reserve(deviceListSize);
    // 读取设备名称列表
    for (uint32_t i = 0; i < deviceListSize; ++i) {
        std::string deviceName;
        out >> deviceName;
        UBSE_LOG_INFO << "deviceName =" << deviceName;
        if (!out.Check()) {
            UBSE_LOG_ERROR << "Failed to deserialize device name at index " << i;
            return UBSE_ERROR_DESERIALIZE_FAILED;
        }
        deviceNameList.push_back(std::move(deviceName));
    }
    UBSE_LOG_INFO << "deviceListSize =" << deviceNameList.size();
    if (!out.Check()) {
        UBSE_LOG_ERROR << "Deserialization check failed after reading all device names";
        return UBSE_ERROR_DESERIALIZE_FAILED;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaDevGetByFilter(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    if (!IsUrmaApiSupported()) {
        return UBSE_ERR_NOT_SUPPORTED;
    }
    uint32_t nodeId{};
    std::vector<std::string> deviceNameList;
    // 反序列化
    uint32_t ret = ParseUrmaDevGetRequest(req, nodeId, deviceNameList);
    if (ret != UBSE_OK) {
        return ret;
    }
    std::vector<UbseUrmaDevBrief> urmaInfo;
    ret = UbseUrmaController::GetInstance().UbseGetUrmaDevsByNodeId(nodeId, urmaInfo);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaController::UbseGetUrmaDevsByNodeId failed," << FormatRetCode(ret);
        return ret;
    }
    // 根据 deviceNameList 进行过滤
    if (!deviceNameList.empty()) {
        std::unordered_set<std::string> allowedDevices(deviceNameList.begin(), deviceNameList.end());
        std::vector<UbseUrmaDevBrief> filtered;
        filtered.reserve(urmaInfo.size());
        for (const auto& info : urmaInfo) {
            if (allowedDevices.find(info.urmaName) != allowedDevices.end()) {
                filtered.push_back(info);
            }
        }
        urmaInfo = std::move(filtered);
    }
    UbseSerialization ubse_req_serial;
    const auto urmaSize = static_cast<uint32_t>(urmaInfo.size());
    ubse_req_serial << urmaSize;
    for (auto& i : urmaInfo) {
        const auto urmaState = static_cast<uint32_t>(i.state);
        const auto urmaType = static_cast<uint32_t>(i.bondingType);
        ubse_req_serial << i.urmaName << urmaType << i.devEid << i.feNames << i.feEids << urmaState;
    }
    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        return UBSE_ERROR_NULLPTR;
    }
    UbseIpcMessage response = {ubse_req_serial.GetBuffer(), static_cast<uint32_t>(ubse_req_serial.GetLength())};
    ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaDevGetByFilter response send failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

UbseResult AllocRspPack(UbseUrmaDevPath& pathInfos, UbseIpcMessage& response)
{
    if (pathInfos.vfePaths.size() != NO_2) {
        UBSE_LOG_ERROR << "vfe path is not equal to 2";
        return UBSE_ERROR;
    }
    auto bufferSize = UbseStringCalcSize(pathInfos.bondingPath, UBSE_MAX_URMA_PATH_LENGTH - 1);
    for (const auto& path : pathInfos.vfePaths) {
        bufferSize += UbseStringCalcSize(path, UBSE_MAX_URMA_PATH_LENGTH - 1);
    }
    bufferSize += UbseStringCalcSize(pathInfos.bondingEid, UBSE_MAX_URMA_PATH_LENGTH - 1);
    if (bufferSize > MAX_BUFFER_SIZE) {
        UBSE_LOG_ERROR << "Requested buffer size " << bufferSize << " exceeds limit " << MAX_BUFFER_SIZE;
        return UBSE_ERROR_INVAL;
    }
    response.buffer = new (std::nothrow) uint8_t[bufferSize];
    if (response.buffer == nullptr) {
        return UBSE_ERROR_NULLPTR;
    }
    response.length = bufferSize;
    UbsePackUtil packUtil(response.buffer, response.length);

    if (!packUtil.UbsePackString(pathInfos.bondingPath, UBSE_MAX_URMA_PATH_LENGTH - 1)) {
        return UBSE_ERROR;
    }
    if (!packUtil.UbsePackString(pathInfos.vfePaths[0], UBSE_MAX_URMA_PATH_LENGTH - 1)) {
        return UBSE_ERROR;
    }
    if (!packUtil.UbsePackString(pathInfos.vfePaths[1], UBSE_MAX_URMA_PATH_LENGTH - 1)) {
        return UBSE_ERROR;
    }
    if (!packUtil.UbsePackString(pathInfos.bondingEid, UBSE_MAX_URMA_PATH_LENGTH - 1)) {
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaDevAlloc(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    if (!IsUrmaApiSupported()) {
        return UBSE_ERR_NOT_SUPPORTED;
    }
    if (req.buffer == nullptr) {
        UBSE_LOG_ERROR << "UbseUrmaDevAlloc IPC request info is null.";
        return UBSE_ERROR_NULLPTR;
    }
    const char* str = reinterpret_cast<const char*>(req.buffer); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
    uint32_t strlen = strnlen(str, UBSE_URMA_NAME_MAX);
    if (strlen >= UBSE_URMA_NAME_MAX) {
        return UBSE_URMACONTRL_ERROR_DEV_NAME_INVALID;
    }
    std::string name(str, strlen);
    UbseUrmaDevPath devInfos;
    uint32_t ret = UbseUrmaController::GetInstance().UbseAllocUrmaDev(name, devInfos);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaController::UbseAllocUrmaDev failed," << FormatRetCode(ret);
        return ret;
    }

    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        return UBSE_ERROR_NULLPTR;
    }
    UbseIpcMessage response = {nullptr, 0};
    ret = AllocRspPack(devInfos, response);
    if (ret != UBSE_OK) {
        delete[] response.buffer;
        response.buffer = nullptr;
        UBSE_LOG_ERROR << "AllocRspPack failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
    delete[] response.buffer;
    response.buffer = nullptr;
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaDevAlloc response send failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaDevFree(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    if (!IsUrmaApiSupported()) {
        return UBSE_ERR_NOT_SUPPORTED;
    }
    if (req.buffer == nullptr) {
        UBSE_LOG_ERROR << "UbseUrmaDevFree IPC request info is null.";
        return UBSE_ERROR_NULLPTR;
    }
    const char* str = reinterpret_cast<const char*>(req.buffer); // NOLINT(cppcoreguidelines-pro-type-reinterpret-cast)
    uint32_t strlen = strnlen(str, UBSE_URMA_NAME_MAX);
    if (strlen >= UBSE_URMA_NAME_MAX) {
        return UBSE_ERROR;
    }
    std::string name(str, strlen);
    uint32_t ret = UbseUrmaController::GetInstance().UbseFreeUrmaDev(name);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaController::UbseFreeUrmaDev failed," << FormatRetCode(ret);
        return ret;
    }

    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        return UBSE_ERROR_NULLPTR;
    }
    UbseIpcMessage response = {nullptr, 0};
    ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaDevFree response send failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaDevGetLocal(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    if (!IsUrmaApiSupported()) {
        return UBSE_ERR_NOT_SUPPORTED;
    }
    if (req.buffer == nullptr) {
        UBSE_LOG_ERROR << "UbseUrmaDevGetLocal IPC request info is null.";
        return UBSE_ERROR_NULLPTR;
    }
    std::vector<std::string> nameInfos;
    std::vector<uint32_t> status;
    std::vector<uint64_t> hwResIds;
    uint32_t ret = UbseUrmaController::GetInstance().UbseUrmaGetDevs(nameInfos, status, hwResIds);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaGetDevs failed," << FormatRetCode(ret);
        return ret;
    }

    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        return UBSE_ERROR_NULLPTR;
    }
    UbseIpcMessage response = {nullptr, 0};
    ret = LocalDevPack(nameInfos, status, hwResIds, response);
    if (ret != UBSE_OK) {
        delete[] response.buffer;
        response.buffer = nullptr;
        UBSE_LOG_ERROR << "LocalDevPack failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
    delete[] response.buffer;
    response.buffer = nullptr;
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaDevGetLocal response send failed." << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaQosCreateReqUnpack(const uint8_t* buffer, uint32_t len, std::vector<EtsQosConfig>& configs)
{
    if (buffer == nullptr) {
        return UBSE_ERROR_NULLPTR;
    }
    const uint8_t* ptr = buffer;
    uint32_t remaining = len;
    if (remaining < sizeof(uint32_t)) {
        UBSE_LOG_ERROR << "Buffer too small for itemCount";
        return UBSE_ERROR_DESERIALIZE_FAILED;
    }
    uint32_t itemCount;
    errno_t err = memcpy_s(&itemCount, sizeof(uint32_t), ptr, sizeof(uint32_t));
    if (err != EOK) {
        UBSE_LOG_ERROR << "Failed to copy itemCount";
        return UBSE_ERROR_DESERIALIZE_FAILED;
    }
    ptr += sizeof(uint32_t);
    remaining -= sizeof(uint32_t);
    if (itemCount > NO_2) {
        UBSE_LOG_ERROR << "Invalid itemCount=" << itemCount;
        return UBSE_ERROR_DESERIALIZE_FAILED;
    }
    configs.reserve(itemCount);
    for (uint32_t i = 0; i < itemCount; ++i) {
        if (remaining < sizeof(uint32_t) * NO_2) {
            UBSE_LOG_ERROR << "Buffer too small for EtsQosConfig[" << i << "]";
            return UBSE_ERROR_DESERIALIZE_FAILED;
        }
        EtsQosConfig config;
        uint32_t priorityValue;
        err = memcpy_s(&priorityValue, sizeof(uint32_t), ptr, sizeof(uint32_t));
        if (err != EOK) {
            UBSE_LOG_ERROR << "Failed to copy priority";
            return UBSE_ERROR_DESERIALIZE_FAILED;
        }
        ptr += sizeof(uint32_t);
        uint32_t bandwidthValue;
        err = memcpy_s(&bandwidthValue, sizeof(uint32_t), ptr, sizeof(uint32_t));
        if (err != EOK) {
            UBSE_LOG_ERROR << "Failed to copy bandwidth";
            return UBSE_ERROR_DESERIALIZE_FAILED;
        }
        config.bandwidth = bandwidthValue * NO_1000;
        config.priority = static_cast<EtsPriority>(priorityValue);
        ptr += sizeof(uint32_t);
        remaining -= sizeof(uint32_t) * NO_2;
        configs.push_back(std::move(config));
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaQosCreateNative(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    if (req.buffer == nullptr) {
        UBSE_LOG_ERROR << "UbseUrmaQosCreateNative request info is null.";
        return UBSE_ERROR_NULLPTR;
    }

    std::vector<EtsQosConfig> configs;
    auto ret = UbseUrmaQosCreateReqUnpack(req.buffer, req.length, configs);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "Failed to unpack QosCreate request, ret=" << ret;
        return ret;
    }

    ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosCreate(configs);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosCreate failed," << FormatRetCode(ret);
        return ret;
    }

    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        return UBSE_ERROR_NULLPTR;
    }
    UbseIpcMessage response = {nullptr, 0};
    ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaQosCreateNative response send failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}

uint32_t UbseUrmaControllerApi::UbseUrmaQosQueryNative(const UbseIpcMessage& req, const UbseRequestContext& context)
{
    if (req.buffer != nullptr || req.length != 0) {
        UBSE_LOG_ERROR << "UbseUrmaQosQueryNative should not have request data.";
        return UBSE_ERR_INVALID_ARG;
    }

    std::vector<EtsQosConfig> configs;
    auto ret = UbseUrmaControllerQos<EtsQosConfig>::GetInstance().UbseUrmaQosQuery(configs);
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaController::UbseUrmaQosQuery failed," << FormatRetCode(ret);
        return ret;
    }

    UbseIpcMessage response = {nullptr, 0};
    ret = QosGetPack(configs, response);
    if (ret != UBSE_OK) {
        return ret;
    }

    auto apiServerModule = UbseContext::GetInstance().GetModule<UbseApiServerModule>();
    if (apiServerModule == nullptr) {
        UBSE_LOG_ERROR << "Get api server module failed";
        delete[] response.buffer;
        response.buffer = nullptr;
        return UBSE_ERROR_NULLPTR;
    }

    ret = apiServerModule->SendResponse(UBSE_OK, context.requestId, response);
    delete[] response.buffer;
    response.buffer = nullptr;
    if (ret != UBSE_OK) {
        UBSE_LOG_ERROR << "UbseUrmaQosQueryNative response send failed," << FormatRetCode(ret);
        return UBSE_ERROR;
    }
    return UBSE_OK;
}
} // namespace ubse::urmaController