#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_NETWORK_ADAPTER_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_NETWORK_ADAPTER_H_

/*
// 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.
*/

#include <algorithm>
#include <array>
#include <charconv>
#include <cstdint>
#include <filesystem>  // NOLINT
#include <fstream>
#include <functional>
#include <limits>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "boost/system/error_code.hpp"  // NOLINT
#include "bmcweb_config.h"
#include "app.hpp"
#include "http_request.hpp"
#include "logging.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "human_sort.hpp"
#include "error_messages.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "dbus_utils.hpp"
#include "location_utils.hpp"
#include <nlohmann/json.hpp>
#include "managed_store.hpp"
#include "managed_store_types.hpp"
#include "sdbusplus/message/native_types.hpp"
#include "sdbusplus/unpack_properties.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 static_cast<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 (std::string(bmcDirectPathIntf).find(portId) != std::string::npos) {
    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["Location"]["PartLocation"]["LocationType"] =
                    "Slot";
                asyncResp->res.jsonValue["Location"]["PartLocationContext"] =
                    chassisLocationCode;

                asyncResp->res.jsonValue["Oem"]["Google"]["ConnectionPath"] =
                    "DIRECT";
                asyncResp->res
                    .jsonValue["Location"]["Oem"]["Google"]["Devpath"] =
                    "/phys/" + chassisLocationCode + "/" + locationCode;
                // recursively find the full oem devpath and PartLocationContext
                redfish::location_util::getLocationContextWithOemDevpath(
                    asyncResp, "/Location"_json_pointer,
                    "/xyz/openbmc_project/inventory/system/board/" + chassisId +
                        "/contained_by");
              });
        });
  } else if (std::string(bmcSidePathIntf).find(portId) != std::string::npos) {
    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

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_NETWORK_ADAPTER_H_
