/*
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/
#pragma once

#include "app.hpp"
#include "dbus_utility.hpp"
#include "health.hpp"
#include "human_sort.hpp"
#include "managed_store_types.hpp"
#include "openbmc_dbus_rest.hpp"
#include "query.hpp"
#include "redfish_util.hpp"
#include "registries/privilege_registry.hpp"
#include "utils/dbus_utils.hpp"

#include <boost/system/error_code.hpp>
#include <sdbusplus/asio/property.hpp>
#include <sdbusplus/unpack_properties.hpp>
#include <utils/location_utils.hpp>

#include "managed_store.hpp"

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{

constexpr char const* networkAdapterInventoryIntf =
    "xyz.openbmc_project.Inventory.Item.NetworkAdapter";
constexpr char const* portInventoryIntf =
    "xyz.openbmc_project.Inventory.Item.Port";
constexpr char const* inventoryPrefix = "/xyz/openbmc_project/inventory";

#ifdef UNIT_TEST_BUILD
constexpr const char* netSysfsPath = sysfsNetBasePathUT;
#else
constexpr const char* netSysfsPath = "/sys/class/net/";
#endif

// Helper function to read a file and return its contents as a string
static bool readOneLineFile(const std::filesystem::path& filePath,
                            std::string& content)
{
    try
    {
        std::ifstream ifs(filePath);
        if (ifs.is_open() && std::getline(ifs, content))
        {
            ifs.close();
            return true;
        }
    }
    catch (...)
    {}
    return false;
}

// Helper function for convert a string to uint64 type
// if string is invalid, return default val instead
static uint64_t stringToUint64(const std::string_view str, uint64_t defVal = 0)
{
    uint64_t value = defVal;
    std::from_chars(str.begin(), str.end(), value);
    return value;
}

static std::vector<std::string> sysfsGetEtherDevList()
{
    std::vector<std::string> ethList;
    // Loop through the directory looking for redfish log files
    for (const std::filesystem::directory_entry& dirEnt :
         std::filesystem::directory_iterator(netSysfsPath))
    {
        std::string type;
        // ignore non-ethernet device
        if (readOneLineFile(dirEnt.path() / "type", type) &&
            stringToUint64(type) == 1)
        {
            ethList.push_back(dirEnt.path().filename());
        }
    }

    return ethList;
}

static std::vector<std::string> sysfsGetEthAddrList(const std::string& portName)
{
    std::vector<std::string> addrList;
    std::filesystem::path macPath =
        std::filesystem::path(netSysfsPath) / portName / "address";
    std::string mac;
    try
    {
        std::ifstream ifs(macPath);
        if (ifs.is_open())
        {
            while (std::getline(ifs, mac))
            {
                addrList.push_back(std::move(mac));
            }
        }
    }
    catch (...)
    {}
    return addrList;
}

// gsys uses ethtool ETHTOOL_GLINK, which checks IFF_UP and carriers.
// LinkStatus follows the same metrics with LinkState
static std::string sysfsGetLinkState(const std::string& portName)
{
    std::filesystem::path carrierPath =
        std::filesystem::path(netSysfsPath) / portName / "carrier";
    std::filesystem::path ifflagPath =
        std::filesystem::path(netSysfsPath) / portName / "flags";

    std::string flags;
    std::string carrier;
    if (readOneLineFile(ifflagPath, flags) &&
        static_cast<bool>(stringToUint64(flags) | IFF_UP) &&
        readOneLineFile(carrierPath, carrier) && stringToUint64(carrier) == 1)
    {
        return "Enabled";
    }

    return "Disabled";
}

static double sysfsGetSpeedGbps(const std::string& portName)
{
    std::filesystem::path speedPath =
        std::filesystem::path(netSysfsPath) / portName / "speed";
    std::string speed;

    if (readOneLineFile(speedPath, speed))
    {
        return double(stringToUint64(speed)) / 1000;
    }

    return 0;
}

static nlohmann::json sysfsGetNetworkPortMetrics(const std::string& portName)
{
    nlohmann::json metrics;
    std::filesystem::path statPath =
        std::filesystem::path(netSysfsPath) / portName / "statistics";

    std::string carrierChanges;
    std::string rxCrcErrors;
    std::string rxErrors;
    std::string rxDropped;
    std::string rxPackets;
    if (readOneLineFile(std::filesystem::path(netSysfsPath) / portName /
                            "carrier_changes",
                        carrierChanges))
    {
        metrics["CarrierChanges"] = stringToUint64(
            carrierChanges, std::numeric_limits<uint64_t>::max());
    }
    if (readOneLineFile(statPath / "rx_crc_errors", rxCrcErrors))
    {
        metrics["RXCRCErrors"] =
            stringToUint64(rxCrcErrors, std::numeric_limits<uint64_t>::max());
    }
    if (readOneLineFile(statPath / "rx_errors", rxErrors))
    {
        metrics["RXErrors"] =
            stringToUint64(rxErrors, std::numeric_limits<uint64_t>::max());
    }
    if (readOneLineFile(statPath / "rx_dropped", rxDropped))
    {
        metrics["ReceivedPacketsDropped"] =
            stringToUint64(rxDropped, std::numeric_limits<uint64_t>::max());
    }
    if (readOneLineFile(statPath / "rx_packets", rxPackets))
    {
        metrics["ReceivedPackets"] = stringToUint64(rxPackets, 0);
    }

    return metrics;
}

template <typename Func, typename... Args>
auto handleChassisNetworkAdapterCommon(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string chassisId, Func funcSysfs, Func funcDBus, Args... args)
    -> decltype(funcSysfs(asyncResp, chassisId, args...),
                funcDBus(asyncResp, chassisId, args...))
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    managedStore::ManagedObjectStoreContext context(asyncResp);

    dbus_utils::getProperty<std::string>(
        "xyz.openbmc_project.EntityManager",
        "/xyz/openbmc_project/inventory/system/board/" + chassisId + "/BmcNet",
        "xyz.openbmc_project.Configuration.BmcNet", "Name", context,
        [asyncResp, chassisId, funcSysfs, funcDBus,
         args...](const boost::system::error_code& ec2,
                  const std::string& bmcNetName) {
        if (ec2 || bmcNetName != "BmcNet")
        {
            // non-bmc chassis
            funcDBus(asyncResp, chassisId, args...);
        }
        else
        {
            // bmc chassis
            funcSysfs(asyncResp, chassisId, args...);
        }
    });
}

inline void handleChassisNetworkAdapterCollectionGetSysfs(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId)
{
    /**
     * Functions triggers appropriate requests
     */
    asyncResp->res.jsonValue["@odata.type"] =
        "#NetworkAdapterCollection.NetworkAdapterCollection";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "NetworkAdapters");
    asyncResp->res.jsonValue["Name"] =
        "Network adapter Collection for chassis " + chassisId;
    nlohmann::json& members = asyncResp->res.jsonValue["Members"];
    members = nlohmann::json::array();
    nlohmann::json::object_t member;
    member["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "NetworkAdapters", "0");
    members.push_back(std::move(member));
    asyncResp->res.jsonValue["Members@odata.count"] = members.size();
}
// Chassis NetworkAdapters, this URL will show all the NetworkAdapterCollection
// information
inline void handleChassisNetworkAdapterCollectionGetDBus(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId)
{
    // mapper call lambda
    constexpr std::array<std::string_view, 2> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Board",
        "xyz.openbmc_project.Inventory.Item.Chassis"};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        inventoryPrefix, 0, interfaces, requestContext,
        [asyncResp, chassisId, requestContext](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            if (ec == boost::system::errc::host_unreachable)
            {
                messages::resourceNotFound(asyncResp->res, "Chassis",
                                           chassisId);
                return;
            }
            BMCWEB_LOG_ERROR << "Failed to get chassis subtree:" << ec.what();
            messages::internalError(asyncResp->res);
            return;
        }

        // Iterate over all retrieved ObjectPaths.
        for (const auto& [path, connectionNames] : subtree)
        {
            sdbusplus::message::object_path objPath(path);
            if (objPath.filename() != chassisId)
            {
                continue;
            }

            if (connectionNames.empty())
            {
                BMCWEB_LOG_DEBUG << "Got 0 Connection names";
                continue;
            }

            asyncResp->res.jsonValue["@odata.type"] =
                "#NetworkAdapterCollection.NetworkAdapterCollection";
            asyncResp->res.jsonValue["@odata.id"] =
                crow::utility::urlFromPieces("redfish", "v1", "Chassis",
                                             chassisId, "NetworkAdapters");
            asyncResp->res.jsonValue["Name"] = "NetworkAdapter Collection";

            // Get /network_adapter association
            dbus_utils::getAssociationEndPoints(
                path + "/network_adapter", requestContext,
                [asyncResp,
                 chassisId](const boost::system::error_code& ec1,
                            const dbus::utility::MapperEndPoints& resp) {
                nlohmann::json& members = asyncResp->res.jsonValue["Members"];
                members = nlohmann::json::array();

                if (ec1)
                {
                    // "/network_adapter" association is optional for chassis
                    BMCWEB_LOG_DEBUG
                        << "Cannot get chassis NetworkAdapter association:"
                        << ec1.what();
                    asyncResp->res.jsonValue["Members@odata.count"] = 0;
                    return;
                }

                std::vector<std::string> leafNames;
                for (const auto& nic : resp)
                {
                    sdbusplus::message::object_path nicPath(nic);
                    leafNames.push_back(nicPath.filename());
                }

                std::sort(leafNames.begin(), leafNames.end(),
                          AlphanumLess<std::string>());

                for (const auto& leafName : leafNames)
                {
                    nlohmann::json::object_t member;
                    member["@odata.id"] = crow::utility::urlFromPieces(
                        "redfish", "v1", "Chassis", chassisId,
                        "NetworkAdapters", leafName);
                    members.push_back(std::move(member));
                }
                asyncResp->res.jsonValue["Members@odata.count"] = resp.size();
            }); // end association lambda

            return; // No need to check other ObjectPaths

        } // end Iterate over all retrieved ObjectPaths

        // chassisId is not found
        messages::resourceNotFound(asyncResp->res, "Chassis", chassisId);
    });
}

// Chassis NetworkAdapters, this URL will show all the NetworkAdapterCollection
// information
inline void handleChassisNetworkAdapterCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId)
{
    handleChassisNetworkAdapterCommon(
        app, req, asyncResp, chassisId,
        handleChassisNetworkAdapterCollectionGetSysfs,
        handleChassisNetworkAdapterCollectionGetDBus);
}

inline void requestRoutesChassisNetworkAdapterCollection(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/NetworkAdapters/")
        .privileges(redfish::privileges::getNetworkAdapterCollection)
        .methods(boost::beast::http::verb::get)(std::bind_front(
            handleChassisNetworkAdapterCollectionGet, std::ref(app)));
}

inline void buildNetworkAdapterDBus(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId,
    const std::string& service, const std::string& networkAdapterPath)
{

    asyncResp->res.jsonValue["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
                                     "NetworkAdapters", networkAdapterId);

    asyncResp->res.jsonValue["@odata.type"] =
        "#NetworkAdapter.v1_9_0.NetworkAdapter";
    asyncResp->res.jsonValue["Name"] = networkAdapterId;
    asyncResp->res.jsonValue["Id"] = networkAdapterId;
    asyncResp->res.jsonValue["Status"]["State"] = "Enabled";

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);

    dbus_utils::getProperty<std::string>(
        service, networkAdapterPath, networkAdapterInventoryIntf,
        "StatusHealth", requestContext,
        [asyncResp](const boost::system::error_code& ec,
                    const std::string& statusHealth) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Get StatusHealth property failed:"
                             << ec.what();
            messages::internalError(asyncResp->res);
            return;
        }

        if (statusHealth.empty())
        {
            BMCWEB_LOG_ERROR << "Empty StatusHealth property";
            messages::internalError(asyncResp->res);
            return;
        }

        asyncResp->res.jsonValue["Status"]["Health"] = statusHealth;
    });

    dbus_utils::getAssociationEndPoints(
        networkAdapterPath + "/all_ports", requestContext,
        [asyncResp, chassisId,
         networkAdapterId](const boost::system::error_code& ec,
                           const dbus::utility::MapperEndPoints& resp) {
        if (ec || resp.empty())
        {
            return; // no ports = no failures
        }
        nlohmann::json reference;
        reference["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
            networkAdapterId, "Ports");
        asyncResp->res.jsonValue["Ports"] = std::move(reference);
    });
}

inline void handleChassisNetworkAdapterGetSysfs(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId)
{

    // currently we only define one network adapter id and put all the bmc ports
    // under it.
    asyncResp->res.jsonValue["@odata.type"] = "#NetworkAdapter.NetworkAdapter";
    asyncResp->res.jsonValue["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
                                     "NetworkAdapters", networkAdapterId);
    asyncResp->res.jsonValue["Name"] = "Network adapter";
    asyncResp->res.jsonValue["Ports"]["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
                                     "NetworkAdapters", networkAdapterId,
                                     "Ports");
}

inline void handleChassisNetworkAdapterGetDBus(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        networkAdapterInventoryIntf};
    // mapper call chassis
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        inventoryPrefix, 0, interfaces, requestContext,
        [asyncResp, chassisId, networkAdapterId, requestContext](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "Get NetworkAdapter inventory failed:"
                             << ec.what();
            messages::internalError(asyncResp->res);
            return;
        }

        // Iterate over all retrieved ObjectPaths.
        for (const auto& [objectPath, serviceMap] : subtree)
        {
            std::string networkAdapterPath =
                crow::utility::urlFromPieces(
                    chassisId, networkAdapterId).buffer();
            if (!objectPath.ends_with(networkAdapterPath))
            {
                continue;
            }

            if (serviceMap.empty())
            {
                BMCWEB_LOG_DEBUG << "Got 0 Connection names";
                continue;
            }
            const std::string& serviceName = serviceMap[0].first;
            buildNetworkAdapterDBus(asyncResp, chassisId, networkAdapterId,
                                    serviceName, objectPath);
            return;
        }

        // chassisId is not found
        std::string networkAdapterPath =
            crow::utility::urlFromPieces(
                chassisId, networkAdapterId).buffer();
        messages::resourceNotFound(asyncResp->res, "Chassis/NetworkAdapter",
                                   networkAdapterId);
    });
}

inline void handleChassisNetworkAdapterGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId)
{
    handleChassisNetworkAdapterCommon(
        app, req, asyncResp, chassisId, handleChassisNetworkAdapterGetSysfs,
        handleChassisNetworkAdapterGetDBus, networkAdapterId);
}

inline void requestRoutesChassisNetworkAdapter(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/NetworkAdapters/<str>/")
        .privileges(redfish::privileges::getNetworkAdapter)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleChassisNetworkAdapterGet, std::ref(app)));
}

inline void handleNetworkPortCollectionGetSysfs(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId)
{
    /**
     * Functions triggers appropriate requests on DBus
     */

    // currently we only define one network adapter and put all the ports under
    // it.
    asyncResp->res.jsonValue["@odata.type"] = "#PortCollection.PortCollection";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
        networkAdapterId, "Ports");
    asyncResp->res.jsonValue["Name"] = "Network ports";
    nlohmann::json& members = asyncResp->res.jsonValue["Members"];
    members = nlohmann::json::array();
    for (auto& i : sysfsGetEtherDevList())
    {
        nlohmann::json::object_t member;
        member["@odata.id"] = crow::utility::urlFromPieces(
            "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
            networkAdapterId, "Ports", i);
        members.push_back(std::move(member));
    }
    asyncResp->res.jsonValue["Members@odata.count"] = members.size();
}

inline void buildNetworkPortCollectionDBus(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId,
    const std::string& networkAdapterPath)
{
    asyncResp->res.jsonValue["@odata.type"] = "#PortCollection.PortCollection";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
        networkAdapterId, "Ports");
    asyncResp->res.jsonValue["Name"] = "Network Port Collection";

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    dbus_utils::getAssociationEndPoints(
        networkAdapterPath + "/all_ports", requestContext,
        [asyncResp, chassisId,
         networkAdapterId](const boost::system::error_code& ec,
                           const dbus::utility::MapperEndPoints& resp) {
        nlohmann::json& members = asyncResp->res.jsonValue["Members"];
        members = nlohmann::json::array();
        if (ec)
        {
            BMCWEB_LOG_DEBUG << "Cannot find chassis /all_ports association:"
                             << ec.what();
            asyncResp->res.jsonValue["Members@odata.count"] = 0;
            return;
        }

        std::vector<std::string> leafNames;
        for (const auto& port : resp)
        {
            sdbusplus::message::object_path portPath(port);
            leafNames.push_back(portPath.filename());
        }

        std::sort(leafNames.begin(), leafNames.end(),
                  AlphanumLess<std::string>());

        for (const auto& leafName : leafNames)
        {
            nlohmann::json::object_t member;
            member["@odata.id"] = crow::utility::urlFromPieces(
                "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
                networkAdapterId, "Ports", leafName);
            members.push_back(std::move(member));
        }
        asyncResp->res.jsonValue["Members@odata.count"] = members.size();
    }); // end association lambda
}

inline void handleNetworkPortCollectionGetDBus(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId)
{
    constexpr std::array<std::string_view, 1> interfaces = {
        networkAdapterInventoryIntf};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        inventoryPrefix, 0, interfaces, requestContext,
        [asyncResp, chassisId, networkAdapterId, requestContext](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            if (ec == boost::system::errc::host_unreachable)
            {
                messages::resourceNotFound(
                    asyncResp->res, "#NetworkAdapter.v1_9_0.NetworkAdapter",
                    networkAdapterId);
                return;
            }
            BMCWEB_LOG_ERROR << "Failed to get " << networkAdapterInventoryIntf
                             << " due to :" << ec.what();
            messages::internalError(asyncResp->res);
            return;
        }

        // Iterate over all retrieved ObjectPaths.
        for (const auto& [path, connectionNames] : subtree)
        {
            std::string networkAdapterPath =
                crow::utility::urlFromPieces(
                    chassisId, networkAdapterId).buffer();
            if (!path.ends_with(networkAdapterPath))
            {
                continue;
            }

            if (connectionNames.empty())
            {
                BMCWEB_LOG_DEBUG << "Got 0 Connection names";
                continue;
            }

            buildNetworkPortCollectionDBus(asyncResp, chassisId,
                                           networkAdapterId, path);
            break;
        } // end Iterate over all retrieved ObjectPaths
    });
}

inline void handleNetworkPortCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId)
{
    handleChassisNetworkAdapterCommon(
        app, req, asyncResp, chassisId, handleNetworkPortCollectionGetSysfs,
        handleNetworkPortCollectionGetDBus, networkAdapterId);
}

inline void requestRoutesNetworkPortCollection(App& app)
{
    BMCWEB_ROUTE(app, "/redfish/v1/Chassis/<str>/NetworkAdapters/<str>/Ports/")
        .privileges(redfish::privileges::getPortCollection)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleNetworkPortCollectionGet, std::ref(app)));
}

inline void handleNetworkPortGetSysfs(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId,
    const std::string& portId)
{
    asyncResp->res.jsonValue["@odata.type"] = "#Port.Port";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
        networkAdapterId, "Ports", portId);
    asyncResp->res.jsonValue["Id"] = portId;
    asyncResp->res.jsonValue["Metrics"]["@odata.id"] =
        crow::utility::urlFromPieces("redfish", "v1", "Chassis", chassisId,
                                     "NetworkAdapters", networkAdapterId,
                                     "Ports", portId, "Metrics");
    if (portId == bmcDirectPathIntf)
    {
        managedStore::ManagedObjectStoreContext requestContext(asyncResp);
        dbus_utils::getProperty<std::string>(
            "xyz.openbmc_project.EntityManager",
            "/xyz/openbmc_project/inventory/system/board/" + chassisId +
                "/BmcNet",
            "xyz.openbmc_project.Configuration.BmcNet", "LocationCode",
            requestContext,
            [asyncResp, chassisId](const boost::system::error_code& ec,
                                   const std::string& locationCode) {
            if (ec)
            {
                BMCWEB_LOG_ERROR << "Fail to get LocationCode for front cable: "
                                 << ec.what();
                return;
            }
            // Get Chassis location code
            managedStore::ManagedObjectStoreContext requestContext2(asyncResp);
            dbus_utils::getProperty<std::string>(
                "xyz.openbmc_project.EntityManager",
                "/xyz/openbmc_project/inventory/system/board/" + chassisId,
                "xyz.openbmc_project.Inventory.Decorator.LocationCode",
                "LocationCode", requestContext2,
                [asyncResp, locationCode,
                 chassisId](const boost::system::error_code& ec2,
                            const std::string& chassisLocationCode) {
                if (ec2)
                {
                    BMCWEB_LOG_ERROR << "Fail to get LocationCode for chassis: "
                                     << ec2.what();
                    return;
                }
                asyncResp->res
                    .jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
                    locationCode;
                asyncResp->res.jsonValue["Oem"]["Google"]["ConnectionPath"] =
                    "DIRECT";
                asyncResp->res
                    .jsonValue["Location"]["Oem"]["Google"]["Devpath"] =
                    "/phys/" + chassisLocationCode + "/" + locationCode;
                // recursively find the full devpath for this chassis
                redfish::location_util::getOemDevpathLocation(
                    asyncResp, "/Location"_json_pointer,
                    "/xyz/openbmc_project/inventory/system/board/" + chassisId +
                        "/contained_by");
            });
        });
    }
    else if (portId == bmcSidePathIntf)
    {
        constexpr std::array<std::string_view, 1> interfaces = {
            "xyz.openbmc_project.Configuration.Port"};
        managedStore::ManagedObjectStoreContext requestContext3(asyncResp);
        managedStore::GetManagedObjectStore()->getSubTreePaths(
            "/xyz/openbmc_project/inventory/system/cable/", 0, interfaces,
            requestContext3,
            [asyncResp, portId](
                const boost::system::error_code& ec3,
                const dbus::utility::MapperGetSubTreePathsResponse& cableList) {
            if (ec3)
            {
                BMCWEB_LOG_ERROR << "Fail to get subtree for cables: "
                                 << ec3.what();
                return;
            }
            for (const auto& pathStr : cableList)
            {
                if (pathStr.size() - portId.size() > 0 &&
                    pathStr.substr(pathStr.size() - portId.size()) == portId)
                {
                    // get the cable location code
                    managedStore::ManagedObjectStoreContext requestContext4(
                        asyncResp);
                    dbus_utils::getProperty<std::string>(
                        "xyz.openbmc_project.EntityManager",
                        pathStr.substr(0, pathStr.size() - portId.size() - 1),
                        "xyz.openbmc_project.Inventory.Decorator.LocationCode",
                        "LocationCode", requestContext4,
                        [asyncResp](const boost::system::error_code& ec4,
                                    const std::string& cableLocationCode) {
                        if (ec4)
                        {
                            BMCWEB_LOG_ERROR
                                << "Fail to get LocationCode for cable: "
                                << ec4.what();
                            return;
                        }
                        asyncResp->res.jsonValue["Location"]["PartLocation"]
                                                ["ServiceLabel"] =
                            cableLocationCode;
                        asyncResp->res
                            .jsonValue["Location"]["Oem"]["Google"]["Devpath"] =
                            "/phys/" + cableLocationCode;
                        asyncResp->res
                            .jsonValue["Oem"]["Google"]["ConnectionPath"] =
                            "SIDE";
                    });
                    break;
                }
            }
        });
    }

    std::vector<std::string> ethList = sysfsGetEthAddrList(portId);
    asyncResp->res.jsonValue["Ethernet"]["AssociatedMACAddresses"] =
        std::move(ethList);
    asyncResp->res.jsonValue["LinkState"] = sysfsGetLinkState(portId);
    if (asyncResp->res.jsonValue["LinkState"] == "Enabled")
    {
        asyncResp->res.jsonValue["LinkStatus"] = "LinkUp";
    }
    else
    {
        asyncResp->res.jsonValue["LinkStatus"] = "LinkDown";
    }
    asyncResp->res.jsonValue["CurrentSpeedGbps"] = sysfsGetSpeedGbps(portId);
    asyncResp->res.jsonValue["Name"] = portId;
}

inline void buildNetworkPortDBus(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId,
    const std::string& portId, const std::string& serviceName,
    const std::string& networkPortPath)
{
    asyncResp->res.jsonValue["@odata.type"] = "#Port.v1_9_0.Port";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
        networkAdapterId, "Ports", portId);
    asyncResp->res.jsonValue["Name"] = portId;
    asyncResp->res.jsonValue["Id"] = portId;

    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getAllProperties(
        serviceName, networkPortPath, portInventoryIntf, requestContext,
        [asyncResp, serviceName, networkPortPath](
            const boost::system::error_code& ec,
            const dbus::utility::DBusPropertiesMap& propertiesList) {
        if (ec)
        {
            BMCWEB_LOG_ERROR << "getAllProperties on path " << networkPortPath
                             << " iface " << portInventoryIntf << " service "
                             << serviceName << " failed with code "
                             << ec.what();
            messages::internalError(asyncResp->res);
            return;
        }

        const std::string* linkState = nullptr;
        const std::string* linkStatus = nullptr;
        const double* currentSpeedGbps = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), propertiesList, "LinkState",
            linkState, "LinkStatus", linkStatus, "CurrentSpeedGbps",
            currentSpeedGbps);

        if (!success)
        {
            BMCWEB_LOG_ERROR << "Failed to unpack " << portInventoryIntf;
            messages::internalError(asyncResp->res);
            return;
        }

        if (linkState == nullptr || linkState->empty())
        {
            BMCWEB_LOG_ERROR << "Empty LinkState property in "
                             << portInventoryIntf;
            messages::internalError(asyncResp->res);
            return;
        }
        asyncResp->res.jsonValue["LinkState"] = *linkState;

        if (linkStatus == nullptr || linkStatus->empty())
        {
            BMCWEB_LOG_ERROR << "Empty LinkStatus property in "
                             << portInventoryIntf;
            messages::internalError(asyncResp->res);
            return;
        }
        asyncResp->res.jsonValue["LinkStatus"] = *linkStatus;

        if (currentSpeedGbps == nullptr)
        {
            BMCWEB_LOG_ERROR << "Empty CurrentSpeedGbps property in "
                             << portInventoryIntf;
            messages::internalError(asyncResp->res);
            return;
        }
        asyncResp->res.jsonValue["CurrentSpeedGbps"] = *currentSpeedGbps;
    });
}

inline void handleNetworkPortGetDBus(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId,
    const std::string& portId)
{
    constexpr std::array<std::string_view, 1> interfaces = {portInventoryIntf};
    managedStore::ManagedObjectStoreContext requestContext(asyncResp);
    managedStore::GetManagedObjectStore()->getSubTree(
        inventoryPrefix, 0, interfaces, requestContext,
        [asyncResp, chassisId, networkAdapterId, portId, requestContext](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec)
        {
            if (ec == boost::system::errc::host_unreachable)
            {
                messages::resourceNotFound(asyncResp->res, "#Port.v1_9_0.Port",
                                           portId);
                return;
            }
            BMCWEB_LOG_ERROR << "Failed to get " << portInventoryIntf
                             << " due to:" << ec.what();
            messages::internalError(asyncResp->res);
            return;
        }

        // Iterate over all retrieved ObjectPaths.
        for (const auto& [path, connectionNames] : subtree)
        {
            std::string portIdPath =
                crow::utility::urlFromPieces(
                    chassisId, networkAdapterId, portId).buffer();
            if (!path.ends_with(portIdPath))
            {
                continue;
            }

            if (connectionNames.empty())
            {
                BMCWEB_LOG_DEBUG << "Got 0 Connection names";
                continue;
            }

            const std::string& serviceName = connectionNames[0].first;
            buildNetworkPortDBus(asyncResp, chassisId, networkAdapterId, portId,
                                 serviceName, path);
            return;
        } // end Iterate over all retrieved ObjectPaths

        messages::resourceNotFound(asyncResp->res, "#Port.v1_9_0.Port", portId);
    });
}

inline void
    handleNetworkPortGet(crow::App& app, const crow::Request& req,
                         const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
                         const std::string& chassisId,
                         const std::string& networkAdapterId,
                         const std::string& portId)
{
    handleChassisNetworkAdapterCommon(
        app, req, asyncResp, chassisId, handleNetworkPortGetSysfs,
        handleNetworkPortGetDBus, networkAdapterId, portId);
}

inline void requestRoutesNetworkPort(App& app)
{
    BMCWEB_ROUTE(app,
                 "/redfish/v1/Chassis/<str>/NetworkAdapters/<str>/Ports/<str>/")
        .privileges(redfish::privileges::getPort)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleNetworkPortGet, std::ref(app)));
}

inline void handleNetworkPortMetricGetSysfs(
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId,
    const std::string& portId)
{
    asyncResp->res.jsonValue["@odata.type"] = "#PortMetrics.PortMetrics";
    asyncResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
        "redfish", "v1", "Chassis", chassisId, "NetworkAdapters",
        networkAdapterId, "Ports", portId, "Metrics");
    asyncResp->res.jsonValue["Name"] = "Network port metrics";
    asyncResp->res.jsonValue["Oem"]["Google"]["Networking"] =
        sysfsGetNetworkPortMetrics(portId);
}

inline void handleNetworkPortMetricGetDBus(
    [[maybe_unused]] const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId,
    const std::string& portId)
{
    BMCWEB_LOG_ERROR << "Metric not supported: chassis " << chassisId
                     << " network adapter " << networkAdapterId << " port "
                     << portId;
}

inline void handleNetworkPortMetricGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    const std::string& chassisId, const std::string& networkAdapterId,
    const std::string& portId)
{
    handleChassisNetworkAdapterCommon(
        app, req, asyncResp, chassisId, handleNetworkPortMetricGetSysfs,
        handleNetworkPortMetricGetDBus, networkAdapterId, portId);
}

inline void requestRoutesNetworkPortMetrics(App& app)
{
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Chassis/<str>/NetworkAdapters/<str>/Ports/<str>/Metrics")
        .privileges(redfish::privileges::getPortMetrics)
        .methods(boost::beast::http::verb::get)(
            std::bind_front(handleNetworkPortMetricGet, std::ref(app)));
}

} // namespace redfish
