#ifndef THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_FABRIC_ADAPTERS_H_
#define THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_FABRIC_ADAPTERS_H_

#include <array>
#include <functional>
#include <memory>
#include <string>
#include <string_view>

#include "boost/system/error_code.hpp"  // NOLINT
#include "app.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "utility.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "query.hpp"
#include "registries/privilege_registry.hpp"
#include "collection.hpp"
#include "dbus_utils.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 {

inline void handleAdapterError(const boost::system::error_code& ec,
                               crow::Response& res,
                               const std::string& adapterId) {
  if (ec.value() == boost::system::errc::io_error) {
    messages::resourceNotFound(res, "#FabricAdapter.v1_4_0.FabricAdapter",
                               adapterId);
    return;
  }

  BMCWEB_LOG_ERROR << "DBus method call failed with error " << ec.value();
  messages::internalError(res);
}

inline void getFabricAdapterLocation(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& serviceName, const std::string& fabricAdapterPath) {
  managedStore::ManagedObjectStoreContext requestContext(aResp);
  dbus_utils::getProperty<std::string>(
      serviceName, fabricAdapterPath,
      "xyz.openbmc_project.Inventory.Decorator.LocationCode", "LocationCode",
      requestContext,
      [aResp](const boost::system::error_code& ec,
              const std::string& property) {
        if (ec) {
          if (ec.value() != EBADR) {
            BMCWEB_LOG_ERROR << "DBUS response error for Location";
            messages::internalError(aResp->res);
          }
          return;
        }

        aResp->res.jsonValue["Location"]["PartLocation"]["ServiceLabel"] =
            property;
      });
}

inline void getFabricAdapterAsset(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& serviceName, const std::string& fabricAdapterPath) {
  managedStore::ManagedObjectStoreContext context(aResp);
  managedStore::GetManagedObjectStore()->getAllProperties(
      serviceName, fabricAdapterPath,
      "xyz.openbmc_project.Inventory.Decorator.Asset", context,
      [fabricAdapterPath, aResp{aResp}](
          const boost::system::error_code& ec,
          const dbus::utility::DBusPropertiesMap& propertiesList) {
        if (ec) {
          if (ec.value() != EBADR) {
            BMCWEB_LOG_ERROR << "DBUS response error for Properties";
            messages::internalError(aResp->res);
          }
          return;
        }

        const std::string* serialNumber = nullptr;
        const std::string* model = nullptr;
        const std::string* partNumber = nullptr;
        const std::string* sparePartNumber = nullptr;

        const bool success = sdbusplus::unpackPropertiesNoThrow(
            dbus_utils::UnpackErrorPrinter(), propertiesList, "SerialNumber",
            serialNumber, "Model", model, "PartNumber", partNumber,
            "SparePartNumber", sparePartNumber);

        if (!success) {
          messages::internalError(aResp->res);
          return;
        }

        if (serialNumber != nullptr) {
          aResp->res.jsonValue["SerialNumber"] = *serialNumber;
        }

        if (model != nullptr) {
          aResp->res.jsonValue["Model"] = *model;
        }

        if (partNumber != nullptr) {
          aResp->res.jsonValue["PartNumber"] = *partNumber;
        }

        if (sparePartNumber != nullptr && !sparePartNumber->empty()) {
          aResp->res.jsonValue["SparePartNumber"] = *sparePartNumber;
        }
      });
}

inline void getFabricAdapterState(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& serviceName, const std::string& fabricAdapterPath) {
  managedStore::ManagedObjectStoreContext requestContext(aResp);
  dbus_utils::getProperty<bool>(
      serviceName, fabricAdapterPath, "xyz.openbmc_project.Inventory.Item",
      "Present", requestContext,
      [aResp](const boost::system::error_code& ec, const bool present) {
        if (ec) {
          if (ec.value() != EBADR) {
            BMCWEB_LOG_ERROR << "DBUS response error for State";
            messages::internalError(aResp->res);
          }
          return;
        }

        if (!present) {
          aResp->res.jsonValue["Status"]["State"] = "Absent";
        }
      });
}

inline void getFabricAdapterHealth(
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& serviceName, const std::string& fabricAdapterPath) {
  managedStore::ManagedObjectStoreContext requestContext(aResp);
  dbus_utils::getProperty<bool>(
      serviceName, fabricAdapterPath,
      "xyz.openbmc_project.State.Decorator.OperationalStatus", "Functional",
      requestContext,
      [aResp](const boost::system::error_code& ec, const bool functional) {
        if (ec) {
          if (ec.value() != EBADR) {
            BMCWEB_LOG_ERROR << "DBUS response error for Health";
            messages::internalError(aResp->res);
          }
          return;
        }

        if (!functional) {
          aResp->res.jsonValue["Status"]["Health"] = "Critical";
        }
      });
}

inline void doAdapterGet(const std::shared_ptr<bmcweb::AsyncResp>& aResp,
                         const std::string& systemName,
                         const std::string& adapterId,
                         const std::string& fabricAdapterPath,
                         const std::string& serviceName) {
  aResp->res.addHeader(boost::beast::http::field::link,
                       "</redfish/v1/JsonSchemas/FabricAdapter/"
                       "FabricAdapter.json>; rel=describedby");
  aResp->res.jsonValue["@odata.type"] = "#FabricAdapter.v1_4_0.FabricAdapter";
  aResp->res.jsonValue["Name"] = "Fabric Adapter";
  aResp->res.jsonValue["Id"] = adapterId;
  aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "Systems", systemName, "FabricAdapters", adapterId);

  aResp->res.jsonValue["Status"]["State"] = "Enabled";
  aResp->res.jsonValue["Status"]["Health"] = "OK";

  getFabricAdapterLocation(aResp, serviceName, fabricAdapterPath);
  getFabricAdapterAsset(aResp, serviceName, fabricAdapterPath);
  getFabricAdapterState(aResp, serviceName, fabricAdapterPath);
  getFabricAdapterHealth(aResp, serviceName, fabricAdapterPath);
}

inline bool checkFabricAdapterId(const std::string& adapterPath,
                                 const std::string& adapterId) {
  std::string fabricAdapterName =
      sdbusplus::message::object_path(adapterPath).filename();

  return !(fabricAdapterName.empty() || fabricAdapterName != adapterId);
}

inline void getValidFabricAdapterPath(
    const std::string& adapterId, const std::string& systemName,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    std::function<void(const std::string& fabricAdapterPath,
                       const std::string& serviceName)>&& callback) {
  if (systemName != "system") {
    messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
    return;
  }
  constexpr std::array<std::string_view, 1> interfaces{
      "xyz.openbmc_project.Inventory.Item.FabricAdapter"};

  managedStore::ManagedObjectStoreContext requestContext(aResp);
  managedStore::GetManagedObjectStore()->getSubTree(
      "/xyz/openbmc_project/inventory", 0, interfaces, requestContext,
      [adapterId, aResp, requestContext, callback](
          const boost::system::error_code& ec,
          const dbus::utility::MapperGetSubTreeResponse& subtree) {
        if (ec) {
          handleAdapterError(ec, aResp->res, adapterId);
          return;
        }
        for (const auto& [adapterPath, serviceMap] : subtree) {
          if (checkFabricAdapterId(adapterPath, adapterId)) {
            callback(adapterPath, serviceMap.begin()->first);
            return;
          }
        }
        BMCWEB_LOG_WARNING << "Adapter not found";
        messages::resourceNotFound(aResp->res, "FabricAdapter", adapterId);
      });
}

inline void handleFabricAdapterGet(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& systemName, const std::string& adapterId) {
  if (!redfish::setUpRedfishRoute(app, req, aResp)) {
    return;
  }

  getValidFabricAdapterPath(
      adapterId, systemName, aResp,
      [aResp, systemName, adapterId](const std::string& fabricAdapterPath,
                                     const std::string& serviceName) {
        doAdapterGet(aResp, systemName, adapterId, fabricAdapterPath,
                     serviceName);
      });
}

inline void handleFabricAdapterCollectionGet(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, aResp)) {
    return;
  }
  if (systemName != "system") {
    messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
    return;
  }

  aResp->res.addHeader(boost::beast::http::field::link,
                       "</redfish/v1/JsonSchemas/FabricAdapterCollection/"
                       "FabricAdapterCollection.json>; rel=describedby");
  aResp->res.jsonValue["@odata.type"] =
      "#FabricAdapterCollection.FabricAdapterCollection";
  aResp->res.jsonValue["Name"] = "Fabric Adapter Collection";
  aResp->res.jsonValue["@odata.id"] = crow::utility::urlFromPieces(
      "redfish", "v1", "Systems", systemName, "FabricAdapters");

  constexpr std::array<std::string_view, 1> interfaces{
      "xyz.openbmc_project.Inventory.Item.FabricAdapter"};
  collection_util::getCollectionMembers(
      aResp, boost::urls::url("/redfish/v1/Systems/system/FabricAdapters"),
      interfaces);
}

inline void handleFabricAdapterCollectionHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& systemName) {
  if (!redfish::setUpRedfishRoute(app, req, aResp)) {
    return;
  }
  if (systemName != "system") {
    messages::resourceNotFound(aResp->res, "ComputerSystem", systemName);
    return;
  }
  aResp->res.addHeader(boost::beast::http::field::link,
                       "</redfish/v1/JsonSchemas/FabricAdapterCollection/"
                       "FabricAdapterCollection.json>; rel=describedby");
}

inline void handleFabricAdapterHead(
    crow::App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& aResp,
    const std::string& systemName, const std::string& adapterId) {
  if (!redfish::setUpRedfishRoute(app, req, aResp)) {
    return;
  }

  getValidFabricAdapterPath(
      adapterId, systemName, aResp,
      [aResp, systemName, adapterId](const std::string&, const std::string&) {
        aResp->res.addHeader(boost::beast::http::field::link,
                             "</redfish/v1/JsonSchemas/FabricAdapter/"
                             "FabricAdapter.json>; rel=describedby");
      });
}

inline void requestRoutesFabricAdapterCollection(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
      .privileges(redfish::privileges::getFabricAdapterCollection)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleFabricAdapterCollectionGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/")
      .privileges(redfish::privileges::headFabricAdapterCollection)
      .methods(boost::beast::http::verb::head)(
          std::bind_front(handleFabricAdapterCollectionHead, std::ref(app)));
}

inline void requestRoutesFabricAdapters(App& app) {
  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
      .privileges(redfish::privileges::getFabricAdapter)
      .methods(boost::beast::http::verb::get)(
          std::bind_front(handleFabricAdapterGet, std::ref(app)));

  BMCWEB_ROUTE(app, "/redfish/v1/Systems/<str>/FabricAdapters/<str>/")
      .privileges(redfish::privileges::headFabricAdapter)
      .methods(boost::beast::http::verb::head)(
          std::bind_front(handleFabricAdapterHead, std::ref(app)));
}
}  // namespace redfish

#endif  // THIRD_PARTY_GBMCWEB_REDFISH_CORE_LIB_FABRIC_ADAPTERS_H_
