#include "tlbmc/configs/entity_config_json_impl.h"

#include <stdint.h>

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <filesystem>  // NOLINT: filesystem is commonly used in bmc codebase.
#include <fstream>
#include <memory>
#include <optional>
#include <queue>
#include <string>
#include <string_view>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "absl/strings/substitute.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "g3/macros.h"
#include "time/proto.h"
#include "nlohmann/json_fwd.hpp"
#include "nlohmann/json.hpp"
#include "json_utils.h"
#include "tlbmc/central_config/config.h"
#include "tlbmc/collector/sensor_collector.h"
#include "entity_common_config.pb.h"
#include "tlbmc/configs/entity_config.h"
#include "tlbmc/configs/expression.h"
#include "fan_controller_config.pb.h"
#include "fan_pwm_config.pb.h"
#include "fan_tach_config.pb.h"
#include "hal_common_config.pb.h"
#include "hwmon_temp_sensor_config.pb.h"
#include "intel_cpu_sensor_config.pb.h"
#include "nic_telemetry_config.pb.h"
#include "psu_sensor_config.pb.h"
#include "reading_range_config.pb.h"
#include "reading_transform_config.pb.h"
#include "shared_mem_sensor_config.pb.h"
#include "threshold_config.pb.h"
#include "topology_config.pb.h"
#include "virtual_sensor_config.pb.h"
#include "veeprom.pb.h"
#include "tlbmc/rcu/simple_rcu.h"
#include "tlbmc/redfish/data/stable_id.h"
#include "fru.pb.h"
#include "resource.pb.h"
#include "sensor.pb.h"
#include "router_interface.h"
#include "re2/re2.h"

namespace milotic_tlbmc {

namespace {

using ::crow::RouterInterface;
using ::milotic::authz::GetValueAsArray;
using ::milotic::authz::GetValueAsBool;
using ::milotic::authz::GetValueAsDoubleFromFloatOrInteger;
using ::milotic::authz::GetValueAsJson;
using ::milotic::authz::GetValueAsString;
using ::milotic::authz::GetValueAsUint;
using ::milotic::authz::GetValueAsUintFromStringOrInteger;

// ProbedConfigMap is a map of config name to ProbedConfigData, which is a
// struct containing corresponding config json and matched probed fru_keys.
using ProbedConfigMap = absl::flat_hash_map<std::string, ProbedConfigData>;

// We need to store what has already been probed and ad-hoc FRUs that could be
// probed.
struct ProcessedConfigData {
  ProbedConfigMap probed_config_map;
  absl::flat_hash_map<std::string, nlohmann::json> unscanned_ad_hoc_fru_configs;
};

constexpr absl::string_view kRefreshIntervalKeyword = "RefreshIntervalMs";
constexpr absl::string_view kQueueSizeKeyword = "QueueSize";

constexpr absl::string_view kDownstreamPortKeyword = "PortDownstream";
constexpr absl::string_view kUpstreamConnectionKeyword = "UpstreamConnection";
// We don't set devpath for some configs, e.g. Ncsi Cable, so we can use this
// keyword to skip setting devpath for them.
constexpr absl::string_view kDontSetDevpathKeyword = "DontSetDevpath";
constexpr const char* kProbeKeyword = "ProbeV2";
constexpr const char* kRedfishAggregationKeyword = "REDFISH_AGGREGATION";

constexpr absl::string_view kBmcNetKeyword = "BmcNet";
constexpr absl::string_view kChassisTypeKeyword = "ChassisType";
constexpr absl::string_view kStorageKeyword = "Storage";
constexpr absl::string_view kProcessorKeyword = "Processor";
constexpr absl::string_view kDimmKeyword = "DIMM";
constexpr absl::string_view kFanKeyword = "Fan";
constexpr absl::string_view kRelatedItemKeyword = "RelatedItem";
constexpr absl::string_view kResourceTypeKeyword = "ResourceType";
constexpr absl::string_view kPartLocationTypeKeyword = "PartLocationType";
constexpr absl::string_view kRootChassisLocationCodeKeyword =
    "RootChassisLocationCode";
constexpr absl::string_view kSensorGroupKeyword = "SensorGroup";
constexpr absl::string_view kCpuIdKeyword = "CpuID";
constexpr absl::string_view kDtsOffsetKeyword = "DtsCritOffset";

constexpr std::array<std::pair<std::string_view, SensorUnit>, 7>
    kSupportedSensorUnits = {{
        // go/keep-sorted start
        {"Ampere", SensorUnit::UNIT_AMPERE},
        {"Count", SensorUnit::UNIT_COUNT},
        {"DegreeCelsius", SensorUnit::UNIT_DEGREE_CELSIUS},
        {"Percent", SensorUnit::UNIT_PERCENT},
        {"RPM", SensorUnit::UNIT_REVOLUTION_PER_MINUTE},
        {"Volt", SensorUnit::UNIT_VOLT},
        {"Watt", SensorUnit::UNIT_WATT},
        // go/keep-sorted end
    }};

absl::Status ParseStorageConfig(const nlohmann::json& config,
                                TopologyConfigNode& topology_config_node,
                                size_t index) {
  const nlohmann::json* storage_config_json =
      GetValueAsJson(config, kStorageKeyword);
  if (storage_config_json == nullptr) {
    return absl::OkStatus();
  }

  // We can have multiple storage configs.
  nlohmann::json::array_t storage_configs;
  if (storage_config_json->is_array()) {
    storage_configs = *storage_config_json;
  } else if (storage_config_json->is_object()) {
    storage_configs.push_back(*storage_config_json);
  }

  for (const auto& storage_config : storage_configs) {
    const std::string* storage_id = GetValueAsString(storage_config, "Id");
    if (storage_id == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: Id field is not found for storage config");
    }
    std::string storage_id_with_index = *storage_id;
    absl::StrReplaceAll({{"$index", absl::StrCat(index + 1)}},
                        &storage_id_with_index);
    topology_config_node.add_children_storage_ids(storage_id_with_index);
  }

  return absl::OkStatus();
}

void ParseBmcNetConfig(const nlohmann::json& config, Fru& fru) {
  const std::string* type_str = GetValueAsString(config, "Type");
  if (type_str == nullptr || *type_str != kBmcNetKeyword) {
    return;
  }
  fru.mutable_attributes()->mutable_chassis_properties()->set_bmcnet(true);
}

absl::Status ParsePortConfig(const nlohmann::json& config,
                             TopologyConfigNode& topology_config_node) {
  const std::string* port_type_str = GetValueAsString(config, "Type");
  if (port_type_str == nullptr ||
      (*port_type_str != kUpstreamConnectionKeyword &&
       *port_type_str != kDownstreamPortKeyword)) {
    return absl::OkStatus();
  }

  const std::string* port_name = GetValueAsString(config, "Name");
  if (port_name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Name field is not found for port");
  }

  PortConfig port_config;
  port_config.set_port_name(*port_name);
  if (*port_type_str == kUpstreamConnectionKeyword) {
    if (std::any_of(topology_config_node.upstream_port_configs().cbegin(),
                    topology_config_node.upstream_port_configs().cend(),
                    [&port_name](const PortConfig& upstream_port_config) {
                      return upstream_port_config.port_name() == *port_name;
                    })) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid config: Multiple Upstream connection configs present for ",
          *port_name));
    }
    port_config.set_port_type(PORT_TYPE_UPSTREAM);
    *topology_config_node.add_upstream_port_configs() = std::move(port_config);
  } else if (*port_type_str == kDownstreamPortKeyword) {
    const std::string* port_label = GetValueAsString(config, "Label");
    if (port_label == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: Label field is not found for downstream port");
    }
    port_config.set_port_label(*port_label);
    port_config.set_port_type(PORT_TYPE_DOWNSTREAM);
    topology_config_node.mutable_port_configs()->insert(
        {*port_name, std::move(port_config)});
  }
  return absl::OkStatus();
}

ChassisType ParseChassisType(const nlohmann::json& config) {
  const std::string* chassis_type_str =
      GetValueAsString(config, kChassisTypeKeyword);
  ChassisType chassis_type;
  if (chassis_type_str == nullptr ||
      !ChassisType_Parse(*chassis_type_str, &chassis_type)) {
    LOG(INFO) << "No valid chassis type found for: " << config.dump()
              << " setting to default RackMount";
    chassis_type = CHASSIS_TYPE_RACK_MOUNT;
  }

  return chassis_type;
}

absl::StatusOr<ResourceType> ParseResourceType(const nlohmann::json& config) {
  const std::string* resource_type_str =
      GetValueAsString(config, kResourceTypeKeyword);
  if (resource_type_str == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: No resource type found for config ", config.dump()));
  }

  ResourceType resource_type;
  if (!ResourceType_Parse(*resource_type_str, &resource_type)) {
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid config: Invalid resource type found for config: ",
                     *resource_type_str));
  }

  return resource_type;
}

void ParsePartLocationType(const nlohmann::json& config,
                           TopologyConfigNode& topology_config_node) {
  const std::string* location_type_str =
      GetValueAsString(config, kPartLocationTypeKeyword);
  if (location_type_str == nullptr) {
    LOG(INFO) << "No location type found for config: " << config.dump();
    return;
  }

  PartLocationType location_type;
  if (!PartLocationType_Parse(*location_type_str, &location_type)) {
    LOG(WARNING) << "Invalid resource type found for config: "
                 << *location_type_str;
    return;
  }

  topology_config_node.mutable_location_context()->set_location_type(
      location_type);
}

void ParseRootChassisLocationCode(const nlohmann::json& config,
                                  TopologyConfigNode& topology_config_node) {
  const std::string* root_chassis_location_code =
      GetValueAsString(config, kRootChassisLocationCodeKeyword);
  if (root_chassis_location_code != nullptr) {
    DLOG(INFO) << "Root chassis location code found: "
               << *root_chassis_location_code;
    topology_config_node.set_root_chassis_location_code(
        *root_chassis_location_code);
  }
}

std::optional<RelatedItem> ParseRelatedItem(const nlohmann::json& config) {
  const nlohmann::json* related_item_json =
      GetValueAsJson(config, kRelatedItemKeyword);
  if (related_item_json == nullptr) {
    LOG(INFO) << "No related item found for config: " << config.dump();
    return std::nullopt;
  }
  const std::string* id = GetValueAsString(*related_item_json, "Id");
  if (id == nullptr) {
    LOG(INFO) << "No item name found for related item config: "
              << config.dump();
    return std::nullopt;
  }
  ResourceType type;
  const std::string* type_str = GetValueAsString(*related_item_json, "Type");
  if (type_str == nullptr || !ResourceType_Parse(*type_str, &type)) {
    type = RESOURCE_TYPE_BOARD;
  }

  RelatedItem related_item;
  related_item.set_id(*id);
  related_item.set_type(type);
  return related_item;
}

absl::Status ParseAssetConfig(const nlohmann::json& config, Fru& fru_object) {
  const nlohmann::json* asset_config_ptr = GetValueAsJson(config, "Asset");
  if (asset_config_ptr == nullptr) {
    return absl::OkStatus();
  }

  AssetInfo asset;
  nlohmann::json asset_config = *asset_config_ptr;

  const std::string* manufacturer_ptr =
      GetValueAsString(asset_config, "Manufacturer");
  if (manufacturer_ptr != nullptr) {
    if (absl::AsciiStrToUpper(*manufacturer_ptr) == "$BOARD_MANUFACTURER" &&
        fru_object.data().fru_info().has_board_manufacturer()) {
      asset.set_manufacturer(fru_object.data().fru_info().board_manufacturer());
    } else if (absl::AsciiStrToUpper(*manufacturer_ptr) ==
                   "$PRODUCT_MANUFACTURER" &&
               fru_object.data().fru_info().has_product_manufacturer()) {
      asset.set_manufacturer(
          fru_object.data().fru_info().product_manufacturer());
    } else if (absl::StartsWith(*manufacturer_ptr, "$")) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid Asset config, cannot substitute ", *manufacturer_ptr,
          ". Check this is a valid substitution keyword and scanned Fru "
          "contains this field. Config: ",
          config.dump()));
    } else {
      asset.set_manufacturer(*manufacturer_ptr);
    }
  }

  const std::string* model_ptr = GetValueAsString(asset_config, "Model");
  if (model_ptr != nullptr) {
    if (absl::AsciiStrToUpper(*model_ptr) == "$BOARD_PRODUCT_NAME" &&
        fru_object.data().fru_info().has_board_product_name()) {
      asset.set_product_name(fru_object.data().fru_info().board_product_name());
    } else if (absl::AsciiStrToUpper(*model_ptr) == "$PRODUCT_PRODUCT_NAME" &&
               fru_object.data().fru_info().has_product_product_name()) {
      asset.set_product_name(
          fru_object.data().fru_info().product_product_name());
    } else if (absl::StartsWith(*model_ptr, "$")) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid Asset config, cannot substitute ", *model_ptr,
          ". Check this is a valid substitution keyword and scanned Fru "
          "contains this field."));
    } else {
      asset.set_product_name(*model_ptr);
    }
  }

  const std::string* part_number_ptr =
      GetValueAsString(asset_config, "PartNumber");
  if (part_number_ptr != nullptr) {
    if (absl::AsciiStrToUpper(*part_number_ptr) == "$BOARD_PART_NUMBER" &&
        fru_object.data().fru_info().has_board_part_number()) {
      asset.set_part_number(fru_object.data().fru_info().board_part_number());
    } else if (absl::AsciiStrToUpper(*part_number_ptr) ==
                   "$PRODUCT_PART_NUMBER" &&
               fru_object.data().fru_info().has_product_part_number()) {
      asset.set_part_number(fru_object.data().fru_info().product_part_number());
    } else if (absl::StartsWith(*part_number_ptr, "$")) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid Asset config, cannot substitute ", *part_number_ptr,
          ". Check this is a valid substitution keyword and scanned Fru "
          "contains this field."));
    } else {
      asset.set_part_number(*part_number_ptr);
    }
  }

  const std::string* serial_number_ptr =
      GetValueAsString(asset_config, "SerialNumber");
  if (serial_number_ptr != nullptr) {
    if (absl::AsciiStrToUpper(*serial_number_ptr) == "$BOARD_SERIAL_NUMBER" &&
        fru_object.data().fru_info().has_board_serial_number()) {
      asset.set_serial_number(
          fru_object.data().fru_info().board_serial_number());
    } else if (absl::AsciiStrToUpper(*serial_number_ptr) ==
                   "$PRODUCT_SERIAL_NUMBER" &&
               fru_object.data().fru_info().has_product_serial_number()) {
      asset.set_serial_number(
          fru_object.data().fru_info().product_serial_number());
    } else if (absl::StartsWith(*serial_number_ptr, "$")) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid Asset config, cannot substitute ", *serial_number_ptr,
          ". Check this is a valid substitution keyword and scanned Fru "
          "contains this field."));
    } else {
      asset.set_serial_number(*serial_number_ptr);
    }
  }

  const std::string* version_ptr = GetValueAsString(asset_config, "Version");
  if (version_ptr != nullptr) {
    if (absl::AsciiStrToUpper(*version_ptr) == "$PRODUCT_VERSION" &&
        fru_object.data().fru_info().has_product_version()) {
      asset.set_version(fru_object.data().fru_info().product_version());
    } else if (absl::StartsWith(*version_ptr, "$")) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid Asset config, cannot substitute ", *version_ptr,
          ". Check this is a valid substitution keyword and scanned Fru "
          "contains this field."));
    } else {
      asset.set_version(*version_ptr);
    }
  }

  const std::string* asset_tag_ptr = GetValueAsString(asset_config, "AssetTag");
  if (asset_tag_ptr != nullptr) {
    if (absl::AsciiStrToUpper(*asset_tag_ptr) == "$PRODUCT_ASSET_TAG" &&
        fru_object.data().fru_info().has_product_asset_tag()) {
      asset.set_asset_tag(fru_object.data().fru_info().product_asset_tag());
    } else if (absl::StartsWith(*asset_tag_ptr, "$")) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid Asset config, cannot substitute ", *asset_tag_ptr,
          ". Check this is a valid substitution keyword and scanned Fru "
          "contains this field."));
    } else {
      asset.set_asset_tag(*asset_tag_ptr);
    }
  }

  *fru_object.mutable_data()->mutable_asset_info() = asset;
  return absl::OkStatus();
}

absl::StatusOr<nlohmann::json> GetObject(const nlohmann::json& json_obj,
                                         const std::string& key) {
  auto find_key = json_obj.find(key);
  if (find_key == json_obj.end()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: ", key, " field is not found: ", json_obj.dump()));
  }
  return find_key->get<nlohmann::json>();
}

absl::StatusOr<std::string> ParseConfigName(const nlohmann::json& config) {
  const std::string* name = GetValueAsString(config, "Name");
  if (name == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: Name field is not found: ", config.dump()));
  }
  if (name->empty()) {
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid config: Name field is empty: ", config.dump()));
  }
  return *name;
}

absl::StatusOr<uint64_t> ParseCpuId(const nlohmann::json& config) {
  std::optional<uint64_t> cpu_id =
      GetValueAsUintFromStringOrInteger(config, kCpuIdKeyword);
  if (!cpu_id.has_value()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: CpuID field is not found: ", config.dump()));
  }
  return *cpu_id;
}

bool CheckProbeFieldMatch(const std::string* probe_field, const Fru& fru,
                          absl::string_view fru_field_name) {
  auto find_fru_field = fru.data().fields().find(fru_field_name);
  return probe_field == nullptr ||
         (find_fru_field != fru.data().fields().end() &&
          probe_field != nullptr &&
          RE2::FullMatch(find_fru_field->second, *probe_field));
}

bool CheckI2cInfoMatchOrNull(const uint64_t* bus, const uint64_t* address,
                             const Fru& fru) {
  bool bus_matches_or_null = bus == nullptr || *bus == fru.i2c_info().bus();
  bool address_matches_or_null =
      address == nullptr || *address == fru.i2c_info().address();
  return bus_matches_or_null && address_matches_or_null;
}

// Probes if the ipmi fru matches and updates the fru table and probed
// config map. Return true if probed successfully.
absl::StatusOr<bool> ProbeFru(nlohmann::json& ipmi_fru_object,
                              const nlohmann::json& config,
                              absl::string_view name, const FruTable& fru_table,
                              ProbedConfigMap& probed_config_map) {
  if (!ipmi_fru_object.is_array()) {
    LOG(INFO) << "IpmiFru field is not an array, converting to array";
    ipmi_fru_object = nlohmann::json::array({ipmi_fru_object});
  }
  bool is_fru_probed = false;
  for (const auto& ipmi_fru : ipmi_fru_object) {
    // Get probe fields.
    const auto* board_product_name =
        GetValueAsString(ipmi_fru, "BOARD_PRODUCT_NAME");
    const auto* product_product_name =
        GetValueAsString(ipmi_fru, "PRODUCT_PRODUCT_NAME");
    const auto* bus = GetValueAsUint(ipmi_fru, "BUS");
    const auto* address = GetValueAsUint(ipmi_fru, "ADDRESS");
    const auto* part_number = GetValueAsString(ipmi_fru, "BOARD_PART_NUMBER");
    const auto* board_info_am2 = GetValueAsString(ipmi_fru, "BOARD_INFO_AM2");
    const auto* board_info_am3 = GetValueAsString(ipmi_fru, "BOARD_INFO_AM3");
    const auto* board_info_am4 = GetValueAsString(ipmi_fru, "BOARD_INFO_AM4");
    const auto* product_info_am2 =
        GetValueAsString(ipmi_fru, "PRODUCT_INFO_AM2");
    if (board_product_name == nullptr && product_product_name == nullptr &&
        bus == nullptr && address == nullptr && part_number == nullptr &&
        board_info_am2 == nullptr && board_info_am3 == nullptr &&
        board_info_am4 == nullptr && product_info_am2 == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: IpmiFru field is not a valid probe");
    }

    // Check if the FRU matches the probe.
    for (const auto& [key, fru] : fru_table.key_to_fru()) {
      // We should only be probing raw fru which have the pattern $bus:$address
      if (!RE2::FullMatch(key, R"(^\d+:0x[0-9a-f]+$)") &&
          !RE2::FullMatch(key, R"(^\d+:\d+$)")) {
        LOG(INFO) << "Skipping non-raw fru: " << key;
        continue;
      }

      bool i2c_info_matches_or_null =
          CheckI2cInfoMatchOrNull(bus, address, fru);

      // Check if any of the FRU fields match the probe.
      bool board_product_name_matches_or_null =
          CheckProbeFieldMatch(board_product_name, fru, "BOARD_PRODUCT_NAME");
      bool product_product_name_matches_or_null = CheckProbeFieldMatch(
          product_product_name, fru, "PRODUCT_PRODUCT_NAME");
      bool part_number_matches_or_null =
          CheckProbeFieldMatch(part_number, fru, "BOARD_PART_NUMBER");
      bool board_info_am2_matches_or_null =
          CheckProbeFieldMatch(board_info_am2, fru, "BOARD_INFO_AM2");
      bool board_info_am3_matches_or_null =
          CheckProbeFieldMatch(board_info_am3, fru, "BOARD_INFO_AM3");
      bool board_info_am4_matches_or_null =
          CheckProbeFieldMatch(board_info_am4, fru, "BOARD_INFO_AM4");
      bool product_info_am2_matches_or_null =
          CheckProbeFieldMatch(product_info_am2, fru, "PRODUCT_INFO_AM2");

      // If the FRU doesn't match the probe, continue to the next FRU.
      if (!i2c_info_matches_or_null || !board_product_name_matches_or_null ||
          !product_product_name_matches_or_null ||
          !part_number_matches_or_null || !board_info_am2_matches_or_null ||
          !board_info_am3_matches_or_null || !board_info_am4_matches_or_null ||
          !product_info_am2_matches_or_null) {
        continue;
      }

      // This condition will check that
      // 1. Only configs containing in $index can have multiple Fru probe true
      // 2. A Fru cannot match multiple probes within one config
      // 3. Multiple configs cannot probe true with the same name
      if (probed_config_map.contains(name) &&
          !absl::StrContains(name, "$index")) {
        return absl::InvalidArgumentError(
            absl::StrCat("Invalid config: Frus match the same config multiple"
                         " times but config name does not contain $index : ",
                         name));
      }
      // If we reach here, the FRU matches the probe and is unique.
      is_fru_probed = true;
      auto& probed_data = probed_config_map[name];

      // If the key is in the format of "bus:address", we will parse the bus
      // and address and use them to construct the FruKey object. Otherwise,
      // default to the string representation of the FruKey.
      probed_data.fru_keys.push_back(FruKey(key));
      probed_data.config = config;
      LOG(INFO) << "Matched config: " << name << " with FRU: " << key;
    }
  }

  if (is_fru_probed) {
    auto& probed_data = probed_config_map[name];
    std::sort(probed_data.fru_keys.begin(), probed_data.fru_keys.end());
    return true;
  }

  return false;
}

// Processes probe configs and returns a map of them.
absl::StatusOr<ProcessedConfigData> ProcessConfigs(
    const std::vector<nlohmann::json>& config_list, FruTable& fru_table) {
  ProcessedConfigData processed_config_data;
  ProbedConfigMap probed_config_map;
  absl::flat_hash_map<std::string, nlohmann::json> ad_hoc_fru_config_map;
  // Map to store the temporary config map for configs that have FOUND probe.
  absl::flat_hash_map<std::string, std::vector<ProbedConfigData>>
      pending_config_name_to_probed_configs;
  for (const auto& config : config_list) {
    absl::StatusOr<nlohmann::json> probe_result =
        GetObject(config, kProbeKeyword);
    if (!probe_result.ok()) {
      continue;
    }

    // Find name of the config.
    ECCLESIA_ASSIGN_OR_RETURN(std::string name, ParseConfigName(config));
    name = absl::StrReplaceAll(name, {{" ", "_"}});

    const std::string* probe_str = probe_result->get_ptr<const std::string*>();
    if (probe_str != nullptr) {
      std::string_view probe_str_view(*probe_str);
      // If the probe is TRUE, then add a ready FRU. If the probe
      // is Redfish Aggregation, then add an status_unknown FRU.
      if (probe_str_view == "TRUE" ||
          probe_str_view == kRedfishAggregationKeyword) {
        if (probed_config_map.contains(name)) {
          return absl::InvalidArgumentError(
              absl::StrCat("Invalid config: Multiple configs with TRUE probe"
                           " have the same name: ",
                           name));
        }
        auto& probed_data = probed_config_map[name];
        probed_data.fru_keys.push_back(FruKey(name));
        probed_data.config = config;
        Fru entity_object;
        entity_object.mutable_attributes()->set_key(name);
        entity_object.mutable_attributes()->set_status(STATUS_READY);
        // For Redfish Aggregation, mark the fru as not found for now
        if (probe_str_view == kRedfishAggregationKeyword) {
          entity_object.mutable_attributes()->set_status(STATUS_UNKNOWN);
        }
        fru_table.mutable_key_to_fru()->insert({name, entity_object});
        continue;
      }
      if (probe_str_view == "FALSE") {
        continue;
      }
      // Store the config in the temporary map with key as FOUND probe
      // and handle the config later.
      if (absl::StartsWith(probe_str_view, "FOUND('") &&
          absl::EndsWith(probe_str_view, "')")) {
        absl::string_view found_config_name = absl::StripSuffix(
            absl::StripPrefix(probe_str_view, "FOUND('"), "')");
        ProbedConfigData probed_data;
        probed_data.fru_keys.push_back(FruKey(name));
        probed_data.config = config;
        pending_config_name_to_probed_configs[found_config_name].push_back(
            probed_data);
        continue;
      }
    }
    nlohmann::json probe = *probe_result;
    // Perform probe.
    // Match Fru if config contains IPMI FRU probe.
    auto ipmi_fru_it = probe.find("IpmiFru");
    if (ipmi_fru_it == probe.end()) {
      return absl::InvalidArgumentError(
          "Invalid config: IpmiFru field is not a valid probe");
    }
    auto ipmi_fru_object = ipmi_fru_it->get<nlohmann::json>();
    absl::StatusOr<bool> is_fru_probed =
        ProbeFru(ipmi_fru_object, config, name, fru_table, probed_config_map);
    if (!is_fru_probed.ok()) {
      return is_fru_probed.status();
    }

    // If the config is supposed to attach to an existing fru, we need to create
    // copies of the fru for each config so they can independently have
    // different asset fields.
    if (probe.contains("AttachToExistingFru") && *is_fru_probed) {
      std::vector<FruKey> new_fru_keys;
      auto& probed_data = probed_config_map[name];
      for (size_t i = 0; i < probed_data.fru_keys.size(); i++) {
        std::string config_name_with_index = name;
        absl::StrReplaceAll({{"$index", std::to_string(i + 1)}},
                            &config_name_with_index);

        FruKey fru_key = probed_data.fru_keys[i];
        Fru fru_copy = fru_table.key_to_fru().at(fru_key.ToString());
        fru_copy.mutable_attributes()->set_key(config_name_with_index);
        fru_table.mutable_key_to_fru()->insert(
            {config_name_with_index, std::move(fru_copy)});
        new_fru_keys.push_back(FruKey(config_name_with_index));
      }

      probed_config_map[name].fru_keys = std::move(new_fru_keys);
    }

    if (!*is_fru_probed && probe.contains("AdHocFruConfig")) {
      ad_hoc_fru_config_map[name] = config;
    }
  }

  // Post-process the configs with FOUND probe.
  // Using topological sort (bfs) to find all the configs which FOUND probe
  // rule is fulfilled. This is to avoid the recursion approach in
  // https://github.com/openbmc/entity-manager/blob/7f51d32fb69f3bb6c4eabf685a27b57f345445cb/src/entity_manager/perform_scan.cpp#L582
  std::queue<std::string> found_target_candidates;
  for (const auto& [name, _] : probed_config_map) {
    if (pending_config_name_to_probed_configs.find(name) !=
        pending_config_name_to_probed_configs.end()) {
      found_target_candidates.push(name);
    }
  }
  while (!found_target_candidates.empty()) {
    const std::string name = found_target_candidates.front();
    found_target_candidates.pop();
    auto found_config_it = pending_config_name_to_probed_configs.find(name);
    if (found_config_it != pending_config_name_to_probed_configs.end()) {
      for (const auto& found_config_data : found_config_it->second) {
        const std::string config_name =
            found_config_data.fru_keys[0].ToString();
        if (probed_config_map.contains(config_name) &&
            !absl::StrContains(name, "$index")) {
          return absl::InvalidArgumentError(
              absl::StrCat("Invalid config: Multiple configs with FOUND probe"
                           " have the same name: ",
                           config_name));
        }
        found_target_candidates.push(config_name);
        probed_config_map[config_name] = found_config_data;
        Fru entity_object;
        entity_object.mutable_attributes()->set_key(config_name);
        entity_object.mutable_attributes()->set_status(STATUS_READY);
        fru_table.mutable_key_to_fru()->insert({config_name, entity_object});
        LOG(INFO) << "FOUND " << name << ", appending config " << config_name;
      }
      pending_config_name_to_probed_configs.erase(found_config_it);
    }
  }
  processed_config_data.probed_config_map = std::move(probed_config_map);
  processed_config_data.unscanned_ad_hoc_fru_configs =
      std::move(ad_hoc_fru_config_map);
  return processed_config_data;
}

void SortChildrenResourceIds(TopologyConfig& topology_config) {
  for (auto& [_, node] : *topology_config.mutable_topology_config_nodes()) {
    std::sort(node.mutable_children_chassis_ids()->pointer_begin(),
              node.mutable_children_chassis_ids()->pointer_end(),
              [](const std::string* id_1, const std::string* id_2) {
                return *id_1 < *id_2;
              });
    std::sort(node.mutable_children_cable_ids()->pointer_begin(),
              node.mutable_children_cable_ids()->pointer_end(),
              [](const std::string* id_1, const std::string* id_2) {
                return *id_1 < *id_2;
              });
    std::sort(node.mutable_children_storage_ids()->pointer_begin(),
              node.mutable_children_storage_ids()->pointer_end(),
              [](const std::string* id_1, const std::string* id_2) {
                return *id_1 < *id_2;
              });
  }
}

void SetDefaultRelatedItem(EntityCommonConfig& entity_common_config) {
  // By default, if no related item is specified, the sensor related item
  // will be the parent board of the config it is defined in.
  RelatedItem default_related_board;
  default_related_board.set_id(entity_common_config.board_config_key());
  default_related_board.set_type(RESOURCE_TYPE_BOARD);
  *entity_common_config.mutable_related_item() = default_related_board;
}

absl::StatusOr<const nlohmann::json::array_t> GetExposesElements(
    const nlohmann::json& config, absl::string_view name) {
  absl::StatusOr<nlohmann::json> exposes = GetObject(config, "Exposes");
  if (!exposes.ok()) {
    return exposes.status();
  }
  const nlohmann::json::array_t* elements =
      exposes->get_ptr<const nlohmann::json::array_t*>();
  if (elements == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: The JSON field `Exposes` is not an array", name));
  }
  return *elements;
}

}  // namespace

template <class TypeName>
struct TypeComparator {
  // Compared by the first element which is the type name.
  bool operator()(const std::pair<std::string_view, TypeName>& lhs,
                  const std::pair<std::string_view, TypeName>& rhs) const {
    return lhs.first < rhs.first;
  }
};

struct TopologyConfigNodePtrComparator {
  bool operator()(const TopologyConfigNode* lhs,
                  const TopologyConfigNode* rhs) const {
    return lhs->location_context().devpath() >
           rhs->location_context().devpath();
  }
};

constexpr std::array<std::pair<std::string_view, HwmonTempSensorType>, 4>
    kSupportedHwmonTempSensorTypes = {{
        // go/keep-sorted start
        {"MAX31725", HWMON_TEMP_SENSOR_TYPE1_MAX31725},
        {"MAX31732", HWMON_TEMP_SENSOR_TYPE3_MAX31732},
        {"SA56004", HWMON_TEMP_SENSOR_TYPE4_SA56004},
        {"TMP75", HWMON_TEMP_SENSOR_TYPE2_TMP75},
        // go/keep-sorted end
    }};

constexpr auto kSupportedPsuSensorTypes =
    std::to_array<std::pair<std::string_view, PsuSensorType>>({
        // go/keep-sorted start
        {"ADM1266", PSU_SENSOR_TYPE1_ADM1266},
        {"ADM1272", PSU_SENSOR_TYPE2_ADM1272},
        {"LTC2991", PSU_SENSOR_TYPE4_LTC2991},
        {"LTC4287", PSU_SENSOR_TYPE9_LTC4287},
        {"LX6301", PSU_SENSOR_TYPE14_LX6301},
        {"Q50SN12072", PSU_SENSOR_TYPE10_Q50SN12072},
        {"Q54SN120A4", PSU_SENSOR_TYPE11_Q54SN120A4},
        {"RAA228228", PSU_SENSOR_TYPE5_RAA228228},
        {"RAA229639", PSU_SENSOR_TYPE13_RAA229639},
        {"SBTSI_I3C", PSU_SENSOR_TYPE15_SBTSI_I3C},
        {"TDA38725", PSU_SENSOR_TYPE6_TDA38725},
        {"TDA38740", PSU_SENSOR_TYPE7_TDA38740},
        {"TPS25990", PSU_SENSOR_TYPE12_TPS25990},
        {"TPS546E25", PSU_SENSOR_TYPE16_TPS546E25},
        {"XDPE1A2G5B", PSU_SENSOR_TYPE8_XDPE1A2G5B},
        {"pmbus", PSU_SENSOR_TYPE3_PMBUS},
        // go/keep-sorted end
    });

constexpr std::array<std::pair<std::string_view, FanControllerType>, 1>
    kSupportedFanControllerTypes = {{
        // go/keep-sorted start
        {"MAX31790", FAN_CONTROLLER_TYPE_MAX31790},
        // go/keep-sorted end
    }};

constexpr std::array<std::pair<std::string_view, FanPwmType>, 1>
    kSupportedFanPwmTypes = {{
        // go/keep-sorted start
        {"I2CFan", PWM_SENSOR_TYPE_I2C_FAN},
        // go/keep-sorted end
    }};

constexpr std::array<std::pair<std::string_view, FanTachType>, 1>
    kSupportedFanTachTypes = {{
        // go/keep-sorted start
        {"I2CFan", TACH_SENSOR_TYPE_I2C_FAN},
        // go/keep-sorted end
    }};

constexpr std::array<std::pair<std::string_view, SharedMemSensorType>, 1>
    kSupportedSharedMemSensorTypes = {{
        // go/keep-sorted start
        {"SharedMemSensor", SHARED_MEM_SENSOR_TYPE_TYPE1_NUMERIC_SENSOR},
        // go/keep-sorted end
    }};

constexpr std::array<std::pair<std::string_view, IntelCpuSensorType>, 1>
    kSupportedIntelCpuSensorTypes = {
        // go/keep-sorted start
        {{"XeonCPU", INTEL_CPU_SENSOR_TYPE1_XEON_CPU}}
        // go/keep-sorted end
};

// For each type of sensor config within our EntityConfig, we need to check if
// the sensor is associated with an assembly. To do so, we perform a lookup in
// the TopologyConfig and FruTable to check the resource type of the assigned
// board_config_key, if an Assembly, we propagate the sensor config to the
// parent.
// Assigned board_config_keys are guaranteed to be valid in the TopologyConfig,
// and fru_key in the topology config will be valid in the FruTable since these
// are where these values are set from.
void EntityConfigJsonImpl::PropagateSensorsFromAssemblyToBoard(
    EntityConfigJsonImplImmutableData& data,
    const TopologyConfig& topology_config, const FruTable& fru_table) {
  for (auto& config : data.hwmon_temp_sensor_configs) {
    auto node_it = topology_config.topology_config_nodes().find(
        config.entity_common_config().board_config_key());

    if (node_it != topology_config.topology_config_nodes().end()) {
      auto fru_it =
          fru_table.key_to_fru().find(node_it->second.fru_info().fru_key());

      /// Propagate sensor config to parent board if the sensor is associated
      // with an assembly.
      if (fru_it != fru_table.key_to_fru().end() &&
          fru_it->second.attributes().resource_type() ==
              RESOURCE_TYPE_ASSEMBLY) {
        *config.mutable_entity_common_config()->mutable_board_config_key() =
            node_it->second.parent_resource_id();
      }
    }

    // Always set default related item if not specified
    if (!config.entity_common_config().has_related_item()) {
      SetDefaultRelatedItem(*config.mutable_entity_common_config());
    }
  }

  for (auto& config : data.psu_sensor_configs) {
    auto node_it = topology_config.topology_config_nodes().find(
        config.entity_common_config().board_config_key());

    if (node_it != topology_config.topology_config_nodes().end()) {
      auto fru_it =
          fru_table.key_to_fru().find(node_it->second.fru_info().fru_key());

      /// Propagate sensor config to parent board if the sensor is associated
      // with an assembly.
      if (fru_it != fru_table.key_to_fru().end() &&
          fru_it->second.attributes().resource_type() ==
              RESOURCE_TYPE_ASSEMBLY) {
        *config.mutable_entity_common_config()->mutable_board_config_key() =
            node_it->second.parent_resource_id();
      }
    }

    // Always set default related item if not specified
    if (!config.entity_common_config().has_related_item()) {
      SetDefaultRelatedItem(*config.mutable_entity_common_config());
    }
  }

  for (auto& config : data.fan_pwm_configs) {
    auto node_it = topology_config.topology_config_nodes().find(
        config.entity_common_config().board_config_key());

    if (node_it != topology_config.topology_config_nodes().end()) {
      auto fru_it =
          fru_table.key_to_fru().find(node_it->second.fru_info().fru_key());

      /// Propagate sensor config to parent board if the sensor is associated
      // with an assembly.
      if (fru_it != fru_table.key_to_fru().end() &&
          fru_it->second.attributes().resource_type() ==
              RESOURCE_TYPE_ASSEMBLY) {
        *config.mutable_entity_common_config()->mutable_board_config_key() =
            node_it->second.parent_resource_id();
      }
    }
  }

  for (auto& config : data.fan_tach_configs) {
    auto node_it = topology_config.topology_config_nodes().find(
        config.entity_common_config().board_config_key());

    if (node_it != topology_config.topology_config_nodes().end()) {
      auto fru_it =
          fru_table.key_to_fru().find(node_it->second.fru_info().fru_key());

      /// Propagate sensor config to parent board if the sensor is associated
      // with an assembly.
      if (fru_it != fru_table.key_to_fru().end() &&
          fru_it->second.attributes().resource_type() ==
              RESOURCE_TYPE_ASSEMBLY) {
        *config.mutable_entity_common_config()->mutable_board_config_key() =
            node_it->second.parent_resource_id();
      }
    }
  }

  for (auto& config : data.shared_mem_sensor_configs) {
    auto node_it = topology_config.topology_config_nodes().find(
        config.entity_common_config().board_config_key());

    if (node_it != topology_config.topology_config_nodes().end()) {
      auto fru_it =
          fru_table.key_to_fru().find(node_it->second.fru_info().fru_key());

      /// Propagate sensor config to parent board if the sensor is associated
      // with an assembly.
      if (fru_it != fru_table.key_to_fru().end() &&
          fru_it->second.attributes().resource_type() ==
              RESOURCE_TYPE_ASSEMBLY) {
        *config.mutable_entity_common_config()->mutable_board_config_key() =
            node_it->second.parent_resource_id();
      }
    }
  }
}

HwmonTempSensorType EntityConfigJsonImpl::IsHwmonTempSensor(
    std::string_view type) {
  const auto* it =
      std::lower_bound(kSupportedHwmonTempSensorTypes.begin(),
                       kSupportedHwmonTempSensorTypes.end(),
                       std::pair<std::string_view, HwmonTempSensorType>{
                           type, HWMON_TEMP_SENSOR_TYPE0_UNKNOWN},
                       TypeComparator<HwmonTempSensorType>());
  if (it == kSupportedHwmonTempSensorTypes.end() || it->first != type) {
    return HWMON_TEMP_SENSOR_TYPE0_UNKNOWN;
  }
  return it->second;
}

PsuSensorType EntityConfigJsonImpl::IsPsuSensor(std::string_view type) {
  const auto* it = std::lower_bound(kSupportedPsuSensorTypes.begin(),
                                    kSupportedPsuSensorTypes.end(),
                                    std::pair<std::string_view, PsuSensorType>{
                                        type, PSU_SENSOR_TYPE0_UNKNOWN},
                                    TypeComparator<PsuSensorType>());
  if (it == kSupportedPsuSensorTypes.end() || it->first != type) {
    return PSU_SENSOR_TYPE0_UNKNOWN;
  }
  return it->second;
}

FanControllerType EntityConfigJsonImpl::IsFanController(std::string_view type) {
  const auto* it = std::lower_bound(
      kSupportedFanControllerTypes.begin(), kSupportedFanControllerTypes.end(),
      std::pair<std::string_view, FanControllerType>{
          type, FAN_CONTROLLER_TYPE_UNKNOWN},
      TypeComparator<FanControllerType>());
  if (it == kSupportedFanControllerTypes.end() || it->first != type) {
    return FAN_CONTROLLER_TYPE_UNKNOWN;
  }
  return it->second;
}

FanPwmType EntityConfigJsonImpl::IsFanPwm(std::string_view type) {
  const auto* it = std::lower_bound(
      kSupportedFanPwmTypes.begin(), kSupportedFanPwmTypes.end(),
      std::pair<std::string_view, FanPwmType>{type, PWM_SENSOR_TYPE_UNKNOWN},
      TypeComparator<FanPwmType>());
  if (it == kSupportedFanPwmTypes.end() || it->first != type) {
    return PWM_SENSOR_TYPE_UNKNOWN;
  }
  return it->second;
}

FanTachType EntityConfigJsonImpl::IsFanTach(std::string_view type) {
  const auto* it = std::lower_bound(
      kSupportedFanTachTypes.begin(), kSupportedFanTachTypes.end(),
      std::pair<std::string_view, FanTachType>{type, TACH_SENSOR_TYPE_UNKNOWN},
      TypeComparator<FanTachType>());
  if (it == kSupportedFanTachTypes.end() || it->first != type) {
    return TACH_SENSOR_TYPE_UNKNOWN;
  }
  return it->second;
}

SharedMemSensorType EntityConfigJsonImpl::IsSharedMemSensor(
    std::string_view type) {
  const auto* it =
      std::lower_bound(kSupportedSharedMemSensorTypes.begin(),
                       kSupportedSharedMemSensorTypes.end(),
                       std::pair<std::string_view, SharedMemSensorType>{
                           type, SHARED_MEM_SENSOR_TYPE_TYPE0_UNKNOWN},
                       TypeComparator<SharedMemSensorType>());
  if (it == kSupportedSharedMemSensorTypes.end() || it->first != type) {
    return SHARED_MEM_SENSOR_TYPE_TYPE0_UNKNOWN;
  }
  return it->second;
}

IntelCpuSensorType EntityConfigJsonImpl::IsIntelCpuSensor(
    std::string_view type) {
  const auto* it =
      std::lower_bound(kSupportedIntelCpuSensorTypes.begin(),
                       kSupportedIntelCpuSensorTypes.end(),
                       std::pair<std::string_view, IntelCpuSensorType>{
                           type, INTEL_CPU_SENSOR_TYPE0_UNKNOWN},
                       TypeComparator<IntelCpuSensorType>());
  if (it == kSupportedIntelCpuSensorTypes.end() || it->first != type) {
    return INTEL_CPU_SENSOR_TYPE0_UNKNOWN;
  }
  return it->second;
}

bool EntityConfigJsonImpl::IsVirtualSensor(std::string_view type) {
  return type == "VirtualSensor";
}

bool EntityConfigJsonImpl::IsFan(std::string_view type) {
  return type == "Fan";
}

bool EntityConfigJsonImpl::IsNicTelemetry(std::string_view type) {
  return type == "NicTelemetry";
}

bool EntityConfigJsonImpl::IsDimm(std::string_view type) {
  return type == kDimmKeyword;
}

absl::Status EntityConfigJsonImpl::ParseAndPopulateConfig(
    EntityConfigJsonImplImmutableData& data, const nlohmann::json& element,
    absl::string_view config_name_with_index, bool is_subfru,
    bool is_detected) {
  const bool* tlbmc_owned = GetValueAsBool(element, "TlbmcOwned");
  if (tlbmc_owned == nullptr || !*tlbmc_owned) {
    return absl::OkStatus();
  }
  bool tlbmc_supported = false;
  const std::string* type = GetValueAsString(element, "Type");
  if (type == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a string");
  }
  // HWMon temperature sensor.
  HwmonTempSensorType hwmon_temp_sensor_type = IsHwmonTempSensor(*type);
  if (hwmon_temp_sensor_type != HWMON_TEMP_SENSOR_TYPE0_UNKNOWN) {
    tlbmc_supported = true;
    ECCLESIA_ASSIGN_OR_RETURN(HwmonTempSensorConfig hwmon_temp_sensor_config,
                              ParseHwmonTempSensorConfig(hwmon_temp_sensor_type,
                                                         element, is_detected));
    hwmon_temp_sensor_config.mutable_entity_common_config()
        ->set_board_config_key(config_name_with_index);
    data.hwmon_temp_sensor_configs.push_back(
        std::move(hwmon_temp_sensor_config));
  }

  // PSU sensor.
  PsuSensorType psu_sensor_type = IsPsuSensor(*type);
  if (psu_sensor_type != PSU_SENSOR_TYPE0_UNKNOWN) {
    tlbmc_supported = true;
    ECCLESIA_ASSIGN_OR_RETURN(
        PsuSensorConfig psu_sensor_config,
        ParsePsuSensorConfig(psu_sensor_type, element, is_detected));
    psu_sensor_config.mutable_entity_common_config()->set_board_config_key(
        config_name_with_index);
    data.psu_sensor_configs.push_back(std::move(psu_sensor_config));
  }

  // FAN controller
  FanControllerType fan_controller_type = IsFanController(*type);
  if (fan_controller_type != FAN_CONTROLLER_TYPE_UNKNOWN) {
    tlbmc_supported = true;
    ECCLESIA_ASSIGN_OR_RETURN(
        FanControllerConfig fan_controller_config,
        ParseFanControllerConfig(fan_controller_type, element, is_detected));
    data.fan_controller_configs.push_back(std::move(fan_controller_config));
  }

  FanPwmType fan_pwm_type = IsFanPwm(*type);
  if (fan_pwm_type != PWM_SENSOR_TYPE_UNKNOWN) {
    tlbmc_supported = true;
    ECCLESIA_ASSIGN_OR_RETURN(
        FanPwmConfig fan_pwm_config,
        ParseFanPwmConfig(fan_pwm_type, element, is_detected));
    fan_pwm_config.mutable_entity_common_config()->set_board_config_key(
        config_name_with_index);
    data.fan_pwm_configs.push_back(std::move(fan_pwm_config));
  }

  FanTachType fan_tach_type = IsFanTach(*type);
  if (fan_tach_type != TACH_SENSOR_TYPE_UNKNOWN) {
    tlbmc_supported = true;
    ECCLESIA_ASSIGN_OR_RETURN(
        FanTachConfig fan_tach_config,
        ParseFanTachConfig(fan_tach_type, element, is_detected));
    fan_tach_config.mutable_entity_common_config()->set_board_config_key(
        config_name_with_index);
    data.fan_tach_configs.push_back(std::move(fan_tach_config));
  }

  SharedMemSensorType shared_mem_sensor_type = IsSharedMemSensor(*type);
  if (shared_mem_sensor_type != SHARED_MEM_SENSOR_TYPE_TYPE0_UNKNOWN) {
    tlbmc_supported = true;
    ECCLESIA_ASSIGN_OR_RETURN(SharedMemSensorConfig shared_mem_sensor_config,
                              ParseSharedMemSensorConfig(shared_mem_sensor_type,
                                                         element, is_detected));
    shared_mem_sensor_config.mutable_entity_common_config()
        ->set_board_config_key(config_name_with_index);
    data.shared_mem_sensor_configs.push_back(
        std::move(shared_mem_sensor_config));
  }

  IntelCpuSensorType intel_cpu_sensor_type = IsIntelCpuSensor(*type);
  if (intel_cpu_sensor_type != INTEL_CPU_SENSOR_TYPE0_UNKNOWN) {
    tlbmc_supported = true;
    absl::StatusOr<IntelCpuSensorConfig> intel_cpu_sensor_config =
        ParseIntelCpuSensorConfig(intel_cpu_sensor_type, element, is_detected);
    if (!intel_cpu_sensor_config.ok()) {
      return intel_cpu_sensor_config.status();
    }
    intel_cpu_sensor_config->mutable_entity_common_config()
        ->set_board_config_key(config_name_with_index);
    data.intel_cpu_sensor_configs.push_back(*intel_cpu_sensor_config);
  }

  if (IsVirtualSensor(*type)) {
    tlbmc_supported = true;
    ECCLESIA_ASSIGN_OR_RETURN(VirtualSensorConfig virtual_sensor_config,
                              ParseVirtualSensorConfig(element, is_detected));
    virtual_sensor_config.mutable_entity_common_config()->set_board_config_key(
        config_name_with_index);
    data.virtual_sensor_configs.push_back(std::move(virtual_sensor_config));
  }

  // We support these types but they need to be parsed later.
  if (IsFan(*type) || IsDimm(*type)) {
    tlbmc_supported = true;
  }

  if (IsNicTelemetry(*type)) {
    tlbmc_supported = true;
    ECCLESIA_ASSIGN_OR_RETURN(NicTelemetryConfig nic_telemetry_config,
                              ParseNicTelemetryConfig(element, is_detected));
    *nic_telemetry_config.mutable_entity_common_config()
         ->mutable_board_config_key() = config_name_with_index;
    data.nic_telemetry_configs.push_back(std::move(nic_telemetry_config));
  }

  if (!tlbmc_supported) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: Config is TlbmcOwned but does not match any supported "
        "sensor type ",
        *type));
  }

  return absl::OkStatus();
}

void EntityConfigJsonImpl::UpdateFruAndTopology(const RawFruTable& fru_table,
                                                const RawFru& raw_fru) {
  EntityConfigJsonImplData new_data = ReloadConfig(
      fru_table, 0,
      /*reload_fru_and_topology_only=*/ReloadType::kReloadFruAndTopologyOnly);

  if (!new_data.mutable_data.parsed_status.ok()) {
    LOG(WARNING) << "Failed to parse config: "
                 << new_data.mutable_data.parsed_status;
  }

  // Update the mutable data. Should not fail.
  absl::Status update_status =
      data_store_.mutable_data.Update(std::move(new_data.mutable_data));
  if (!update_status.ok()) {
    LOG(WARNING) << "Failed to update FRU and topology: " << update_status;
  }

  if (smart_router_ != nullptr) {
    smart_router_->UpdateTlbmcOwnedUrls();
  }

  if (sensor_collector_ != nullptr) {
    absl::StatusOr<std::string> config_key =
        GetConfigKeyByFruKey(raw_fru.key());
    if (!config_key.ok()) {
      LOG(WARNING) << "Failed to get config key by FRU key: "
                   << config_key.status()
                   << ". Cannot reinitialize sensors for fru: "
                   << raw_fru.key();
      return;
    }
    sensor_collector_->ReinitializeAndScheduleAllSensorsForConfigKey(
        *config_key);
  }
}

EntityConfigJsonImplData EntityConfigJsonImpl::ReloadConfig(
    const RawFruTable& fru_table, size_t ad_hoc_fru_count,
    ReloadType reload_type) {
  EntityConfigJsonImplImmutableData immutable_data;
  EntityConfigJsonImplMutableData mutable_data;

  // Make Readonly copy of the FRU table.
  for (const auto& [key, raw_fru] : fru_table.key_to_raw_fru()) {
    Fru fru;
    Attributes* attributes = fru.mutable_attributes();
    attributes->set_key(raw_fru.key());
    attributes->set_status(Status::STATUS_READY);
    attributes->mutable_refresh_policy()->set_refresh_mode(
        RefreshMode::REFRESH_MODE_ON_DEMAND);

    *fru.mutable_data() = raw_fru.data();
    *fru.mutable_i2c_info() = raw_fru.i2c_info();
    mutable_data.fru_table.mutable_key_to_fru()->insert({key, fru});
  }

  absl::StatusOr<ProcessedConfigData> processed_config_data =
      ProcessConfigs(immutable_config_list_, mutable_data.fru_table);
  if (!processed_config_data.ok()) {
    mutable_data.parsed_status = processed_config_data.status();
    return EntityConfigJsonImplData{
        .immutable_data = std::move(immutable_data),
        .mutable_data = std::move(mutable_data),
        .max_updates_to_mutable_data = ad_hoc_fru_count};
  }

  if (processed_config_data->probed_config_map.empty()) {
    mutable_data.parsed_status =
        absl::InvalidArgumentError("Probe failed for all configs");
    return EntityConfigJsonImplData{
        .immutable_data = std::move(immutable_data),
        .mutable_data = std::move(mutable_data),
        .max_updates_to_mutable_data = ad_hoc_fru_count};
  }

  // This map is used to update the FRU info for it's sub FRUs.
  // Example:
  // {"fru_key_1": {"sub_fru_config_1", "sub_fru_config_2"},
  //  "fru_key_2": {"sub_fru_config_3"}}
  absl::flat_hash_map<std::string, absl::flat_hash_set<std::string>>
      fru_key_to_sub_fru_config;

  // If multiple FRUs match the config, we need to substitute the FRU
  // specific fields in the config with the FRU info and then parse the
  // config.
  for (const auto& [name, config_data] :
       processed_config_data->probed_config_map) {
    // Check if config belongs to a sub FRU.
    // RESOURCE_TYPE_ASSEMBLY indicates a config that is a sub FRU.
    absl::StatusOr<ResourceType> resource_type =
        ParseResourceType(config_data.config);

    if (!resource_type.ok()) {
      mutable_data.parsed_status = resource_type.status();
      return EntityConfigJsonImplData{
          .immutable_data = std::move(immutable_data),
          .mutable_data = std::move(mutable_data),
          .max_updates_to_mutable_data = ad_hoc_fru_count};
    }

    // For each FRU, substitute config variables with FRU info and parse the
    // config.
    // `ProcessConfigs` is already checked to guarantee that only configs with
    // $index will have multiple Fru keys matching.
    for (size_t i = 0; i < config_data.fru_keys.size(); i++) {
      // Create a new topology config node for each FRU.
      TopologyConfigNode topology_config_node;
      std::string config_name_with_index = name;
      absl::StrReplaceAll({{"$index", std::to_string(i + 1)}},
                          &config_name_with_index);
      topology_config_node.set_name(config_name_with_index);

      std::string fru_key = config_data.fru_keys[i].ToString();

      // In the case of a sub FRU, we create an entry in the FruTable keyed by
      // the config name to have separate Fru data from the parent Fru.
      bool is_subfru = *resource_type == RESOURCE_TYPE_ASSEMBLY;
      if (is_subfru) {
        fru_key = config_name_with_index;
        Fru sub_fru_info;
        Attributes* attributes = sub_fru_info.mutable_attributes();
        attributes->set_key(fru_key);
        attributes->set_status(Status::STATUS_READY);
        attributes->mutable_refresh_policy()->set_refresh_mode(
            RefreshMode::REFRESH_MODE_ON_DEMAND);
        mutable_data.fru_table.mutable_key_to_fru()->insert(
            {fru_key, sub_fru_info});
      }

      // Get the FRU object from the fru_key. This is used to update the Fru
      // object fields with Fru information from config.
      // Key is not expected to be invalid.
      Fru& fru = mutable_data.fru_table.mutable_key_to_fru()->at(fru_key);

      fru.mutable_attributes()->set_resource_type(*resource_type);

      if (*resource_type == RESOURCE_TYPE_BOARD) {
        fru.mutable_attributes()
            ->mutable_chassis_properties()
            ->set_chassis_type(ParseChassisType(config_data.config));
      }

      ParsePartLocationType(config_data.config, topology_config_node);
      ParseRootChassisLocationCode(config_data.config, topology_config_node);

      absl::StatusOr<const nlohmann::json::array_t> elements =
          GetExposesElements(config_data.config, name);
      if (!elements.ok()) {
        mutable_data.parsed_status = elements.status();
        return EntityConfigJsonImplData{
            .immutable_data = std::move(immutable_data),
            .mutable_data = std::move(mutable_data),
            .max_updates_to_mutable_data = ad_hoc_fru_count};
      }

      // Get the FRU info for the FRU key. This is used to substitute the FRU
      // specific fields in the config.
      // Key is not expected to be invalid.
      const Fru& fru_info = mutable_data.fru_table.key_to_fru().at(fru_key);
      for (const auto& element_before_fru_substitution : *elements) {
        // Substitute FRU specific fields.
        nlohmann::json element = element_before_fru_substitution;

        // Substitute Bus field.
        const std::string* config_bus = GetValueAsString(element, "Bus");
        if (config_bus != nullptr && fru_info.has_i2c_info() &&
            absl::StrContainsIgnoreCase(*config_bus, "$bus")) {
          absl::string_view config_bus_view(*config_bus);
          absl::StatusOr<std::string> bus_value_substitute_result =
              EvaluateStrExpressionSubstitution(
                  config_bus_view,
                  absl::StrContains(config_bus_view, "$bus") ? "$bus" : "$BUS",
                  absl::StrCat(fru_info.i2c_info().bus()));
          if (!bus_value_substitute_result.ok()) {
            mutable_data.parsed_status = bus_value_substitute_result.status();
            return EntityConfigJsonImplData{
                .immutable_data = std::move(immutable_data),
                .mutable_data = std::move(mutable_data),
                .max_updates_to_mutable_data = ad_hoc_fru_count};
          }
          uint64_t bus_value;
          if (!absl::SimpleAtoi(*bus_value_substitute_result, &bus_value)) {
            LOG(WARNING) << absl::StrCat(
                "Invalid json: Failed to convert value at Bus",
                " to unsigned value: ", config_bus_view);
            return EntityConfigJsonImplData{
                .immutable_data = std::move(immutable_data),
                .mutable_data = std::move(mutable_data),
                .max_updates_to_mutable_data = ad_hoc_fru_count};
          }
          element["Bus"] = bus_value;
        }

        // Substitute Address field.
        const std::string* config_address_str =
            GetValueAsString(element, "Address");
        if (config_address_str != nullptr &&
            absl::StrContainsIgnoreCase(*config_address_str, "$address") &&
            fru_info.has_i2c_info()) {
          element["Address"] =
              absl::StrCat(absl::Hex(fru_info.i2c_info().address()));
        }

        // Substitute $bus and $index in values of all remaining elements in the
        // config.
        for (auto& [key, field_value] : element.items()) {
          const std::string* field_value_str = GetValueAsString(element, key);
          // Special case for RelatedItem, we know this will be nested and want
          // substitution for it.
          if (key == "RelatedItem") {
            const std::string* item_id = GetValueAsString(field_value, "Id");
            if (item_id != nullptr) {
              field_value["Id"] = absl::StrReplaceAll(
                  *item_id, {{"$index", absl::StrCat(i + 1)}});
            }
          }
          // If the field is not a string, continue since we expect substitution
          // only for string fields.
          if (field_value_str == nullptr) {
            continue;
          }
          // Make a copy of the field value string since we will be modifying
          // it in place.
          std::string field_value_str_copy = *field_value_str;
          if (absl::StrContainsIgnoreCase(field_value_str_copy, "$bus")) {
            absl::StatusOr<std::string> field_value_substitute_result =
                EvaluateStrExpressionSubstitution(
                    field_value_str_copy,
                    absl::StrContains(field_value_str_copy, "$bus") ? "$bus"
                                                                    : "$BUS",
                    absl::StrCat(fru_info.i2c_info().bus()));
            if (!field_value_substitute_result.ok()) {
              mutable_data.parsed_status =
                  field_value_substitute_result.status();
              return EntityConfigJsonImplData{
                  .immutable_data = std::move(immutable_data),
                  .mutable_data = std::move(mutable_data),
                  .max_updates_to_mutable_data = ad_hoc_fru_count};
            }
            element[key] = *field_value_substitute_result;
          }

          if (absl::StrContains(field_value_str_copy, "$index")) {
            absl::StatusOr<std::string> field_value_substitute_result =
                EvaluateStrExpressionSubstitution(
                    field_value_str_copy, "$index", absl::StrCat(i + 1));
            if (!field_value_substitute_result.ok()) {
              mutable_data.parsed_status =
                  field_value_substitute_result.status();
              return EntityConfigJsonImplData{
                  .immutable_data = std::move(immutable_data),
                  .mutable_data = std::move(mutable_data),
                  .max_updates_to_mutable_data = ad_hoc_fru_count};
            }
            element[key] = *field_value_substitute_result;
          }
        }

        if (reload_type == ReloadType::kReloadAll) {
          absl::Status config_parse_status = ParseAndPopulateConfig(
              immutable_data, element, config_name_with_index, is_subfru, true);
          if (!config_parse_status.ok()) {
            mutable_data.parsed_status = config_parse_status;
            return EntityConfigJsonImplData{
                .immutable_data = std::move(immutable_data),
                .mutable_data = std::move(mutable_data),
                .max_updates_to_mutable_data = ad_hoc_fru_count};
          }
        }

        absl::Status parse_port_config_status =
            ParsePortConfig(element, topology_config_node);
        if (!parse_port_config_status.ok()) {
          mutable_data.parsed_status = parse_port_config_status;
          return EntityConfigJsonImplData{
              .immutable_data = std::move(immutable_data),
              .mutable_data = std::move(mutable_data),
              .max_updates_to_mutable_data = ad_hoc_fru_count};
        }

        absl::Status parse_processor_status =
            ParseProcessorConfig(mutable_data, element, topology_config_node,
                                 config_name_with_index);
        if (!parse_processor_status.ok()) {
          mutable_data.parsed_status = parse_processor_status;
          return EntityConfigJsonImplData{
              .immutable_data = std::move(immutable_data),
              .mutable_data = std::move(mutable_data),
              .max_updates_to_mutable_data = ad_hoc_fru_count};
        }

        absl::Status parse_dimm_status =
            ParseDimmConfig(mutable_data, element, topology_config_node,
                            config_name_with_index);
        if (!parse_dimm_status.ok()) {
          mutable_data.parsed_status = parse_dimm_status;
          return EntityConfigJsonImplData{
              .immutable_data = std::move(immutable_data),
              .mutable_data = std::move(mutable_data),
              .max_updates_to_mutable_data = ad_hoc_fru_count};
        }

        absl::Status parse_fan_status =
            ParseFanConfig(mutable_data, element, topology_config_node,
                           config_name_with_index);
        if (!parse_fan_status.ok()) {
          mutable_data.parsed_status = parse_fan_status;
          return EntityConfigJsonImplData{
              .immutable_data = std::move(immutable_data),
              .mutable_data = std::move(mutable_data),
              .max_updates_to_mutable_data = ad_hoc_fru_count};
        }

        if (fru_info.attributes().resource_type() == RESOURCE_TYPE_BOARD) {
          ParseBmcNetConfig(element, fru);
        }
      }

      absl::Status parse_storage_status =
          ParseStorageConfig(config_data.config, topology_config_node, i);
      if (!parse_storage_status.ok()) {
        mutable_data.parsed_status = parse_storage_status;
        return EntityConfigJsonImplData{
            .immutable_data = std::move(immutable_data),
            .mutable_data = std::move(mutable_data),
            .max_updates_to_mutable_data = ad_hoc_fru_count};
      }

      absl::Status parse_asset_config_status =
          ParseAssetConfig(config_data.config, fru);
      if (!parse_asset_config_status.ok()) {
        mutable_data.parsed_status = parse_asset_config_status;
        return EntityConfigJsonImplData{
            .immutable_data = std::move(immutable_data),
            .mutable_data = std::move(mutable_data),
            .max_updates_to_mutable_data = ad_hoc_fru_count};
      }

      topology_config_node.mutable_fru_info()->set_fru_key(fru_key);

      mutable_data.topology_config.mutable_fru_configs()->insert(
          {fru_key, config_name_with_index});
      if (is_subfru) {
        topology_config_node.mutable_fru_info()->set_is_sub_fru(true);
        fru_key_to_sub_fru_config[config_data.fru_keys[i].ToString()].insert(
            config_name_with_index);
      }

      // tlbmc does not own assemblies now.
      if ((!GetTlbmcConfig().fru_collector_module().own_cables_in_redfish() &&
           fru_info.attributes().resource_type() == RESOURCE_TYPE_CABLE) ||
          fru_info.attributes().resource_type() == RESOURCE_TYPE_ASSEMBLY) {
        topology_config_node.set_not_owned_by_tlbmc(true);
      }

      // For now, tlBMC doesn't own redfish aggregated FRUs
      if (fru_info.attributes().status() == STATUS_UNKNOWN) {
        topology_config_node.set_not_owned_by_tlbmc(true);
      }

      // If the config has port configs, add the topology config node to the
      // topology config.
      if (!topology_config_node.upstream_port_configs().empty() ||
          !topology_config_node.port_configs().empty()) {
        topology_config_node.set_config_key(config_name_with_index);
        mutable_data.topology_config.mutable_topology_config_nodes()->insert(
            {std::move(config_name_with_index),
             std::move(topology_config_node)});
      }
    }
  }

  // Update the FRU info for sub FRUs.
  for (auto& [fru_key, config_keys] : fru_key_to_sub_fru_config) {
    for (const auto& config_key : config_keys) {
      auto config_key_it =
          mutable_data.topology_config.mutable_fru_configs()->find(fru_key);
      if (config_key_it ==
          mutable_data.topology_config.mutable_fru_configs()->end()) {
        mutable_data.parsed_status = absl::InternalError(
            absl::StrCat("Fru config not found for Sub FRU defined in config: ",
                         config_key));
        return EntityConfigJsonImplData{
            .immutable_data = std::move(immutable_data),
            .mutable_data = std::move(mutable_data),
            .max_updates_to_mutable_data = ad_hoc_fru_count};
      }
      // Topology config is expected to be present in the map as the name is
      // obtained from the map itself.
      TopologyConfigNode& topology_config_node =
          mutable_data.topology_config.mutable_topology_config_nodes()->at(
              config_key_it->second);
      *topology_config_node.mutable_sub_fru_config_keys()->Add() = config_key;
    }
  }

  absl::flat_hash_set<absl::string_view> fru_keys_with_sub_frus;
  for (const auto& [fru_key, _] : mutable_data.fru_table.key_to_fru()) {
    auto it = mutable_data.topology_config.mutable_fru_configs()->find(fru_key);
    if (it == mutable_data.topology_config.mutable_fru_configs()->end()) {
      if (!GetTlbmcConfig().fru_collector_module().allow_dangling_frus()) {
        mutable_data.parsed_status = absl::InternalError(absl::StrCat(
            "Invalid topology: no config with matching probe found for FRU: ",
            fru_key));
        return EntityConfigJsonImplData{
            .immutable_data = std::move(immutable_data),
            .mutable_data = std::move(mutable_data),
            .max_updates_to_mutable_data = ad_hoc_fru_count};
      }
      continue;
    }
    fru_keys_with_sub_frus.insert(it->second);
  }
  for (const auto& [fru_key, sub_fru_config_keys] : fru_key_to_sub_fru_config) {
    fru_keys_with_sub_frus.insert(sub_fru_config_keys.begin(),
                                  sub_fru_config_keys.end());
  }

  absl::Status create_associations_status =
      CreateAssociationsBetweenTopologyConfigNodes(mutable_data.topology_config,
                                                   mutable_data.fru_table,
                                                   fru_keys_with_sub_frus);
  if (!create_associations_status.ok()) {
    mutable_data.parsed_status = create_associations_status;
    return EntityConfigJsonImplData{
        .immutable_data = std::move(immutable_data),
        .mutable_data = std::move(mutable_data),
        .max_updates_to_mutable_data = ad_hoc_fru_count};
  }

  // Sort the children of each Fru
  SortChildrenResourceIds(mutable_data.topology_config);

  // Parse sensors for AdHoc FRUs.
  if (reload_type == ReloadType::kReloadAll) {
    for (const auto& [name, config] :
         processed_config_data->unscanned_ad_hoc_fru_configs) {
      absl::StatusOr<const nlohmann::json::array_t> elements =
          GetExposesElements(config, name);
      if (!elements.ok()) {
        mutable_data.parsed_status = elements.status();
        return EntityConfigJsonImplData{
            .immutable_data = std::move(immutable_data),
            .mutable_data = std::move(mutable_data),
            .max_updates_to_mutable_data = ad_hoc_fru_count};
      }

      for (const auto& element : *elements) {
        absl::Status config_parse_status =
            ParseAndPopulateConfig(immutable_data, element, name, false, false);
        if (!config_parse_status.ok()) {
          mutable_data.parsed_status = config_parse_status;
          return EntityConfigJsonImplData{
              .immutable_data = std::move(immutable_data),
              .mutable_data = std::move(mutable_data),
              .max_updates_to_mutable_data = ad_hoc_fru_count};
        }
      }
    }
  }

  // Propagate sensors defined in Assembly to their parent boards
  PropagateSensorsFromAssemblyToBoard(
      immutable_data, mutable_data.topology_config, mutable_data.fru_table);

  return EntityConfigJsonImplData{
      .immutable_data = std::move(immutable_data),
      .mutable_data = std::move(mutable_data),
      .max_updates_to_mutable_data = ad_hoc_fru_count};
}

ReadingRangeConfigs EntityConfigJsonImpl::ParseReadingRangeConfigs(
    const nlohmann::json& config, std::optional<double> default_min,
    std::optional<double> default_max) {
  ReadingRangeConfigs reading_range_configs;
  std::optional<double> max =
      GetValueAsDoubleFromFloatOrInteger(config, "MaxReading");
  if (max.has_value() || default_max) {
    ReadingRangeConfig max_range;
    max_range.set_type(READING_RANGE_TYPE_MAX);
    max_range.set_reading(!max.has_value() ? *default_max : *max);
    *reading_range_configs.mutable_reading_range_configs()->Add() = max_range;
  }
  std::optional<double> min =
      GetValueAsDoubleFromFloatOrInteger(config, "MinReading");
  if (min.has_value() || default_min) {
    ReadingRangeConfig min_range;
    min_range.set_type(READING_RANGE_TYPE_MIN);
    min_range.set_reading(!min.has_value() ? *default_min : *min);
    *reading_range_configs.mutable_reading_range_configs()->Add() = min_range;
  }
  return reading_range_configs;
}

absl::flat_hash_map<std::string, ReadingRangeConfigs>
EntityConfigJsonImpl::ParseReadingRangeConfigs(
    const nlohmann::json& config, absl::Span<const std::string> labels) {
  absl::flat_hash_map<std::string, ReadingRangeConfigs>
      label_to_reading_range_configs;
  for (const std::string& label : labels) {
    std::string max_key = absl::Substitute("$0_Max", label);
    std::optional<double> max =
        GetValueAsDoubleFromFloatOrInteger(config, max_key);
    if (max.has_value()) {
      ReadingRangeConfig max_range;
      max_range.set_type(READING_RANGE_TYPE_MAX);
      max_range.set_reading(*max);
      ReadingRangeConfigs& max_configs = label_to_reading_range_configs[label];
      *max_configs.mutable_reading_range_configs()->Add() = max_range;
    }

    std::string min_key = absl::Substitute("$0_Min", label);
    std::optional<double> min =
        GetValueAsDoubleFromFloatOrInteger(config, min_key);
    if (min.has_value()) {
      ReadingRangeConfig min_range;
      min_range.set_type(READING_RANGE_TYPE_MIN);
      min_range.set_reading(*min);
      ReadingRangeConfigs& min_configs = label_to_reading_range_configs[label];
      *min_configs.mutable_reading_range_configs()->Add() = min_range;
    }
  }
  return label_to_reading_range_configs;
}

absl::flat_hash_map<std::string, ReadingTransformConfig>
EntityConfigJsonImpl::ParseReadingTransformConfigs(
    const nlohmann::json& config, absl::Span<const std::string> labels) {
  absl::flat_hash_map<std::string, ReadingTransformConfig>
      label_to_reading_transform;
  for (const std::string& label : labels) {
    std::string scale_key = absl::Substitute("$0_Scale", label);
    std::optional<double> scale =
        GetValueAsDoubleFromFloatOrInteger(config, scale_key);
    std::string offset_key = absl::Substitute("$0_Offset", label);
    std::optional<double> offset =
        GetValueAsDoubleFromFloatOrInteger(config, offset_key);
    ReadingTransformConfig reading_transform_config;
    // Only allow custom scale factor > 0 to avoid division by zero
    // https://github.com/openbmc/dbus-sensors/blob/af1724b84b7558037c665d2106ec44d7362aca6b/src/psu/PSUSensorMain.cpp#L738
    if (scale.has_value() && *scale > 0) {
      reading_transform_config.set_scale(*scale);
    }
    if (offset.has_value()) {
      reading_transform_config.set_offset(*offset);
    }
    if (reading_transform_config.has_scale() ||
        reading_transform_config.has_offset()) {
      label_to_reading_transform[label] = reading_transform_config;
    }
  }
  return label_to_reading_transform;
}

absl::StatusOr<HalCommonConfig> EntityConfigJsonImpl::ParseHalCommonConfig(
    const nlohmann::json& config) {
  HalCommonConfig hal_config;
  std::optional<uint64_t> bus =
      GetValueAsUintFromStringOrInteger(config, "Bus");
  if (!bus.has_value()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: element does not have a Bus field: ", config.dump()));
  }
  hal_config.set_bus(*bus);

  const std::string* address = GetValueAsString(config, "Address");
  if (address == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: element does not have an Address field");
  }

  uint64_t address_uint64;
  if (!absl::SimpleHexAtoi(*address, &address_uint64)) {
    return absl::InvalidArgumentError(
        "Invalid config: Address field is not a valid hex number: ");
  }
  hal_config.set_address(address_uint64);
  return hal_config;
}

absl::StatusOr<std::vector<std::string>> EntityConfigJsonImpl::ParseLabels(
    const nlohmann::json& config) {
  const nlohmann::json::array_t* labels = GetValueAsArray(config, "Labels");
  if (labels == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Labels field is not an array");
  }
  std::vector<std::string> labels_vector;
  for (const auto& label : *labels) {
    const std::string* label_str = label.get_ptr<const std::string*>();
    if (label_str == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: label element is not a string");
    }
    labels_vector.push_back(*label_str);
  }
  return labels_vector;
}

absl::StatusOr<std::vector<nic_veeprom::NicTelemetryName>>
EntityConfigJsonImpl::ParseNicTelemetryNames(const nlohmann::json& config) {
  const nlohmann::json::array_t* telemetry_names =
      GetValueAsArray(config, "TelemetryNames");
  if (telemetry_names == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: TelemetryNames field is not an array");
  }
  std::vector<nic_veeprom::NicTelemetryName> telemetry_names_vector;
  for (const auto& telemetry_name : *telemetry_names) {
    const std::string* telemetry_name_str =
        telemetry_name.get_ptr<const std::string*>();
    if (telemetry_name_str == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: TelemetryNames element is not a string");
    }
    nic_veeprom::NicTelemetryName telemetry_name_enum;
    if (!nic_veeprom::NicTelemetryName_Parse(*telemetry_name_str,
                                             &telemetry_name_enum)) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid config: TelemetryNames element is not a valid enum: ",
          *telemetry_name_str));
    }
    telemetry_names_vector.push_back(telemetry_name_enum);
  }
  return telemetry_names_vector;
}

SensorUnit EntityConfigJsonImpl::ParseSensorUnit(const nlohmann::json& config) {
  const std::string* unit_str = GetValueAsString(config, "Unit");
  if (unit_str == nullptr) {
    LOG(INFO) << "No unit found for: " << config.dump()
              << " setting to unknown";
    return SensorUnit::UNIT_UNKNOWN;
  }

  const auto* it = std::lower_bound(
      kSupportedSensorUnits.begin(), kSupportedSensorUnits.end(),
      std::pair<std::string_view, SensorUnit>{*unit_str,
                                              SensorUnit::UNIT_UNKNOWN},
      [](const auto& a, const auto& b) { return a.first < b.first; });
  if (it == kSupportedSensorUnits.end() || it->first != *unit_str) {
    return SensorUnit::UNIT_UNKNOWN;
  }
  return it->second;
}

absl::StatusOr<ThresholdType> EntityConfigJsonImpl::ParseThresholdType(
    std::string_view name) {
  constexpr absl::string_view kUpperCritical = "Upper Critical";
  constexpr absl::string_view kUpperNonCritical = "Upper Non Critical";
  constexpr absl::string_view kLowerCritical = "Lower Critical";
  constexpr absl::string_view kLowerNonCritical = "Lower Non Critical";
  if (absl::EqualsIgnoreCase(name, kUpperCritical)) {
    return THRESHOLD_TYPE_UPPER_CRITICAL;
  }
  if (absl::EqualsIgnoreCase(name, kUpperNonCritical)) {
    return THRESHOLD_TYPE_UPPER_NON_CRITICAL;
  }
  if (absl::EqualsIgnoreCase(name, kLowerCritical)) {
    return THRESHOLD_TYPE_LOWER_CRITICAL;
  }
  if (absl::EqualsIgnoreCase(name, kLowerNonCritical)) {
    return THRESHOLD_TYPE_LOWER_NON_CRITICAL;
  }
  return absl::InvalidArgumentError(absl::StrCat(
      "Invalid config: Type field is not a valid threshold type: ", name));
}

absl::StatusOr<absl::flat_hash_map<std::string, ThresholdConfigs>>
EntityConfigJsonImpl::ParseThresholdConfigs(const nlohmann::json& config) {
  absl::flat_hash_map<std::string, ThresholdConfigs> label_to_threshold_configs;
  if (!config.contains("Thresholds")) {
    return label_to_threshold_configs;
  }
  const nlohmann::json::array_t* threshold_configs =
      GetValueAsArray(config, "Thresholds");
  if (threshold_configs == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Thresholds field is not an array");
  }
  for (const auto& threshold_element : *threshold_configs) {
    const std::string* name = GetValueAsString(threshold_element, "Name");
    if (name == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: Name field is not a string or missing");
    }
    ECCLESIA_ASSIGN_OR_RETURN(ThresholdType threshold_type,
                              ParseThresholdType(*name));

    ThresholdConfig threshold_config;
    threshold_config.set_type(threshold_type);
    std::optional<double> value =
        GetValueAsDoubleFromFloatOrInteger(threshold_element, "Value");
    if (!value.has_value()) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid threshold config: Value field is not a double: config is ",
          threshold_element.dump()));
    }
    threshold_config.set_value(*value);

    if (threshold_element.contains("Label")) {
      const std::string* label = GetValueAsString(threshold_element, "Label");
      if (label == nullptr) {
        return absl::InvalidArgumentError(absl::StrCat(
            "Invalid threshold config: Label field is not a string",
            threshold_element.dump()));
      }
      *label_to_threshold_configs[*label].add_threshold_configs() =
          threshold_config;
    } else {
      *label_to_threshold_configs[""].add_threshold_configs() =
          threshold_config;
    }
  }
  return label_to_threshold_configs;
}

absl::StatusOr<absl::flat_hash_map<std::string, ThresholdConfigs>>
EntityConfigJsonImpl::ParseThresholdConfigsForHwmonTemp(
    const nlohmann::json& config, const std::vector<std::string>& labels) {
  absl::flat_hash_map<std::string, ThresholdConfigs> label_to_threshold_configs;
  if (!config.contains("Thresholds")) {
    return label_to_threshold_configs;
  }
  const nlohmann::json::array_t* threshold_configs =
      GetValueAsArray(config, "Thresholds");
  if (threshold_configs == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Thresholds field is not an array");
  }
  for (const auto& threshold_element : *threshold_configs) {
    const std::string* name = GetValueAsString(threshold_element, "Name");
    if (name == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: Name field is not a string or missing");
    }
    ECCLESIA_ASSIGN_OR_RETURN(ThresholdType threshold_type,
                              ParseThresholdType(*name));

    ThresholdConfig threshold_config;
    threshold_config.set_type(threshold_type);
    std::optional<double> value =
        GetValueAsDoubleFromFloatOrInteger(threshold_element, "Value");
    if (!value.has_value()) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid threshold config: Value field is not a double: config is ",
          threshold_element.dump()));
    }
    threshold_config.set_value(*value);

    for (const auto& label : labels) {
      *label_to_threshold_configs[label].add_threshold_configs() =
          threshold_config;
    }
  }
  return label_to_threshold_configs;
}

absl::StatusOr<absl::flat_hash_map<std::string, std::string>>
EntityConfigJsonImpl::ParseLabelToName(const nlohmann::json& config,
                                       absl::Span<const std::string> labels,
                                       bool ignore_zero_index_name) {
  absl::flat_hash_map<std::string, std::string> label_to_name;
  for (std::size_t i = 0; i < labels.size(); ++i) {
    std::string label = labels[i];
    std::string key =
        absl::Substitute("$0_Name", absl::StrReplaceAll(label, {{" ", "_"}}));
    const std::string* name_str = GetValueAsString(config, key);
    if (name_str == nullptr && !ignore_zero_index_name) {
      // Try the other schema if $0_Name is not found.
      key = (i == 0) ? "Name" : absl::Substitute("Name$0", i);
      name_str = GetValueAsString(config, key);
      if (name_str == nullptr) {
        return absl::InvalidArgumentError(absl::StrCat(
            "Invalid config: Name field is not a string or missing: ",
            config.dump()));
      }
    }

    if (name_str == nullptr) {
      label_to_name[label] = "";
    } else {
      label_to_name[label] = absl::StrReplaceAll(*name_str, {{" ", "_"}});
    }
  }
  return label_to_name;
}

// Configure refresh interval
template <typename T>
absl::Status ParseCommonEntityConfig(const nlohmann::json& config, T& sensor) {
  const auto* refresh_interval =
      GetValueAsUint(config, kRefreshIntervalKeyword);
  if (refresh_interval == nullptr) {
    return absl::OkStatus();
  }
  auto proto_duration = ecclesia::AbslDurationToProtoDuration(
      absl::Milliseconds(*refresh_interval));
  if (!proto_duration.ok()) {
    return proto_duration.status();
  }
  *sensor.mutable_entity_common_config()->mutable_refresh_interval() =
      *proto_duration;

  if (const auto* queue_size = GetValueAsUint(config, kQueueSizeKeyword);
      queue_size != nullptr) {
    sensor.mutable_entity_common_config()->set_queue_size(*queue_size);
  }
  return absl::OkStatus();
}

absl::StatusOr<HwmonTempSensorConfig>
EntityConfigJsonImpl::ParseHwmonTempSensorConfig(HwmonTempSensorType type,
                                                 const nlohmann::json& config,
                                                 bool is_detected) {
  if (type == HWMON_TEMP_SENSOR_TYPE0_UNKNOWN) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a supported HWMon temperature "
        "sensor type");
  }
  HwmonTempSensorConfig hwmon_temp_sensor_config;
  hwmon_temp_sensor_config.set_type(type);

  ECCLESIA_ASSIGN_OR_RETURN(
      *hwmon_temp_sensor_config.mutable_hal_common_config(),
      ParseHalCommonConfig(config));

  ECCLESIA_RETURN_IF_ERROR(
      ParseCommonEntityConfig(config, hwmon_temp_sensor_config));

  // Default reading range for hwmon temperature sensors.
  // From:
  // https://github.com/openbmc/dbus-sensors/blob/af1724b84b7558037c665d2106ec44d7362aca6b/src/hwmon-temp/HwmonTempMain.cpp#L62
  constexpr double kDefaultTempMinReading = -128.0;
  constexpr double kDefaultTempMaxReading = 127.0;
  ReadingRangeConfig max;
  max.set_type(READING_RANGE_TYPE_MAX);
  max.set_reading(kDefaultTempMaxReading);
  ReadingRangeConfig min;
  min.set_type(READING_RANGE_TYPE_MIN);
  min.set_reading(kDefaultTempMinReading);
  ReadingRangeConfigs reading_range_configs;
  *reading_range_configs.add_reading_range_configs() = max;
  *reading_range_configs.add_reading_range_configs() = min;

  std::vector<std::string> labels;
  const nlohmann::json::array_t* labels_array =
      GetValueAsArray(config, "Labels");

  // If the labels array is not present, we use the default label "temp$i".
  if (labels_array == nullptr) {
    for (size_t i = 0;; i++) {
      std::string key = "Name";
      if (i > 0) key += std::to_string(i);
      const std::string* name_str = GetValueAsString(config, key);
      if (name_str == nullptr) {
        break;
      }
      std::string label = absl::Substitute("temp$0", i + 1);
      (*hwmon_temp_sensor_config.mutable_label_to_name())[label] = *name_str;
      (*hwmon_temp_sensor_config.mutable_label_to_reading_ranges())[label] =
          reading_range_configs;
      labels.push_back(label);
    }
  } else {
    // Otherwise, we use the labels array and the labels will be checked against
    // the labels files.
    for (const auto& label : *labels_array) {
      const std::string* label_str = label.get_ptr<const std::string*>();
      if (label_str == nullptr) {
        return absl::InvalidArgumentError(
            "Invalid config: Labels field is not a string array");
      }
      labels.push_back(*label_str);
      (*hwmon_temp_sensor_config
            .mutable_label_to_reading_ranges())[*label_str] =
          reading_range_configs;
    }
    absl::flat_hash_map<std::string, std::string> label_to_name;
    ECCLESIA_ASSIGN_OR_RETURN(label_to_name, ParseLabelToName(config, labels));
    hwmon_temp_sensor_config.mutable_label_to_name()->insert(
        label_to_name.begin(), label_to_name.end());
  }

  std::optional<RelatedItem> related_item = ParseRelatedItem(config);
  if (related_item.has_value()) {
    *hwmon_temp_sensor_config.mutable_entity_common_config()
         ->mutable_related_item() = *related_item;
  }

  absl::flat_hash_map<std::string, ThresholdConfigs> label_to_threshold_configs;
  ECCLESIA_ASSIGN_OR_RETURN(label_to_threshold_configs,
                            ParseThresholdConfigsForHwmonTemp(config, labels));
  hwmon_temp_sensor_config.mutable_label_to_thresholds()->insert(
      label_to_threshold_configs.begin(), label_to_threshold_configs.end());

  const std::string* sensor_group =
      GetValueAsString(config, kSensorGroupKeyword);
  if (sensor_group != nullptr) {
    hwmon_temp_sensor_config.set_sensor_group(*sensor_group);
  }

  hwmon_temp_sensor_config.mutable_entity_common_config()->set_config_detected(
      is_detected);

  return hwmon_temp_sensor_config;
}

absl::StatusOr<FanControllerConfig>
EntityConfigJsonImpl::ParseFanControllerConfig(FanControllerType type,
                                               const nlohmann::json& config,
                                               bool is_detected) {
  if (type == FAN_CONTROLLER_TYPE_UNKNOWN) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a supported Fan controller type");
  }
  FanControllerConfig fan_controller_config;
  fan_controller_config.set_type(type);

  ECCLESIA_ASSIGN_OR_RETURN(*fan_controller_config.mutable_hal_common_config(),
                            ParseHalCommonConfig(config));

  fan_controller_config.mutable_entity_common_config()->set_config_detected(
      is_detected);

  return fan_controller_config;
}

absl::StatusOr<PsuSensorConfig> EntityConfigJsonImpl::ParsePsuSensorConfig(
    PsuSensorType type, const nlohmann::json& config, bool is_detected) {
  if (type == PSU_SENSOR_TYPE0_UNKNOWN) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a supported PSU sensor type");
  }
  PsuSensorConfig psu_sensor_config;
  psu_sensor_config.set_type(type);

  const std::string* name = GetValueAsString(config, "Name");
  if (name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Name field is not a string or missing");
  }
  psu_sensor_config.set_name(*name);

  ECCLESIA_ASSIGN_OR_RETURN(*psu_sensor_config.mutable_hal_common_config(),
                            ParseHalCommonConfig(config));
  ECCLESIA_RETURN_IF_ERROR(ParseCommonEntityConfig(config, psu_sensor_config));

  std::vector<std::string> labels;
  ECCLESIA_ASSIGN_OR_RETURN(labels, ParseLabels(config));

  absl::flat_hash_map<std::string, std::string> label_to_name;
  ECCLESIA_ASSIGN_OR_RETURN(label_to_name,
                            ParseLabelToName(config, labels, true));
  psu_sensor_config.mutable_label_to_name()->insert(label_to_name.begin(),
                                                    label_to_name.end());

  absl::flat_hash_map<std::string, ThresholdConfigs> label_to_threshold_configs;
  ECCLESIA_ASSIGN_OR_RETURN(label_to_threshold_configs,
                            ParseThresholdConfigs(config));
  psu_sensor_config.mutable_label_to_thresholds()->insert(
      label_to_threshold_configs.begin(), label_to_threshold_configs.end());

  absl::flat_hash_map<std::string, ReadingRangeConfigs> label_to_reading_range =
      ParseReadingRangeConfigs(config, labels);
  psu_sensor_config.mutable_label_to_reading_ranges()->insert(
      label_to_reading_range.begin(), label_to_reading_range.end());

  absl::flat_hash_map<std::string, ReadingTransformConfig>
      label_to_reading_transform = ParseReadingTransformConfigs(config, labels);
  psu_sensor_config.mutable_label_to_reading_transform()->insert(
      label_to_reading_transform.begin(), label_to_reading_transform.end());

  std::optional<RelatedItem> related_item = ParseRelatedItem(config);
  if (related_item.has_value()) {
    *psu_sensor_config.mutable_entity_common_config()->mutable_related_item() =
        *related_item;
  }

  const std::string* sensor_group =
      GetValueAsString(config, kSensorGroupKeyword);
  if (sensor_group != nullptr) {
    psu_sensor_config.set_sensor_group(*sensor_group);
  }

  psu_sensor_config.mutable_entity_common_config()->set_config_detected(
      is_detected);

  return psu_sensor_config;
}

absl::StatusOr<FanPwmConfig> EntityConfigJsonImpl::ParseFanPwmConfig(
    FanPwmType type, const nlohmann::json& config, bool is_detected) {
  if (type == PWM_SENSOR_TYPE_UNKNOWN) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a supported Fan PWM type");
  }
  FanPwmConfig fan_pwm_config;
  fan_pwm_config.set_type(type);

  ECCLESIA_ASSIGN_OR_RETURN(*fan_pwm_config.mutable_hal_common_config(),
                            ParseHalCommonConfig(config));

  // Fan PWM has fixed max and min reading ranges.
  ReadingRangeConfig max;
  max.set_type(READING_RANGE_TYPE_MAX);
  max.set_reading(100);
  *fan_pwm_config.mutable_reading_ranges()->add_reading_range_configs() = max;
  ReadingRangeConfig min;
  min.set_type(READING_RANGE_TYPE_MIN);
  min.set_reading(0);
  *fan_pwm_config.mutable_reading_ranges()->add_reading_range_configs() = min;

  const nlohmann::json* connector = GetValueAsJson(config, "Connector");
  if (connector == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Connector field is not a JSON");
  }
  const std::string* name = GetValueAsString(*connector, "PwmName");
  if (name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Connector PwmName field is not a string");
  }
  fan_pwm_config.set_name(*name);
  const uint64_t* index = GetValueAsUint(*connector, "Pwm");
  if (index == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Connector Index field is not a uint64_t");
  }
  fan_pwm_config.set_index(static_cast<int32_t>(*index + 1));

  ECCLESIA_RETURN_IF_ERROR(ParseCommonEntityConfig(config, fan_pwm_config));

  std::optional<RelatedItem> related_item = ParseRelatedItem(config);
  if (related_item.has_value()) {
    *fan_pwm_config.mutable_entity_common_config()->mutable_related_item() =
        *related_item;
  }

  const std::string* sensor_group =
      GetValueAsString(config, kSensorGroupKeyword);
  if (sensor_group != nullptr) {
    fan_pwm_config.set_sensor_group(*sensor_group);
  }

  fan_pwm_config.mutable_entity_common_config()->set_config_detected(
      is_detected);

  return fan_pwm_config;
}

absl::StatusOr<FanTachConfig> EntityConfigJsonImpl::ParseFanTachConfig(
    FanTachType type, const nlohmann::json& config, bool is_detected) {
  if (type == TACH_SENSOR_TYPE_UNKNOWN) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a supported Fan PWM type");
  }
  FanTachConfig fan_tach_config;
  fan_tach_config.set_type(type);

  ECCLESIA_ASSIGN_OR_RETURN(*fan_tach_config.mutable_hal_common_config(),
                            ParseHalCommonConfig(config));

  constexpr int kDefaultMaxFanReading = 25000;
  constexpr int kDefaultMinFanReading = 0;
  ReadingRangeConfigs reading_range_configs = ParseReadingRangeConfigs(
      config, kDefaultMinFanReading, kDefaultMaxFanReading);
  *fan_tach_config.mutable_reading_ranges() = reading_range_configs;

  const std::string* name = GetValueAsString(config, "Name");
  if (name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Name field is not a string or missing");
  }
  fan_tach_config.set_name(*name);
  const uint64_t* index = GetValueAsUint(config, "Index");
  if (index == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Index field is not a uint64_t");
  }
  fan_tach_config.set_index(static_cast<int32_t>(*index + 1));

  absl::flat_hash_map<std::string, ThresholdConfigs> label_to_threshold_configs;
  ECCLESIA_ASSIGN_OR_RETURN(label_to_threshold_configs,
                            ParseThresholdConfigs(config));
  *fan_tach_config.mutable_thresholds() = label_to_threshold_configs[""];

  ECCLESIA_RETURN_IF_ERROR(ParseCommonEntityConfig(config, fan_tach_config));

  std::optional<RelatedItem> related_item = ParseRelatedItem(config);
  if (related_item.has_value()) {
    *fan_tach_config.mutable_entity_common_config()->mutable_related_item() =
        *related_item;
  }

  const std::string* sensor_group =
      GetValueAsString(config, kSensorGroupKeyword);
  if (sensor_group != nullptr) {
    fan_tach_config.set_sensor_group(*sensor_group);
  }

  fan_tach_config.mutable_entity_common_config()->set_config_detected(
      is_detected);

  return fan_tach_config;
}

absl::StatusOr<SharedMemSensorConfig>
EntityConfigJsonImpl::ParseSharedMemSensorConfig(SharedMemSensorType type,
                                                 const nlohmann::json& config,
                                                 bool is_detected) {
  if (type == SHARED_MEM_SENSOR_TYPE_TYPE0_UNKNOWN) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a supported Shared Mem Sensor type");
  }
  SharedMemSensorConfig shared_mem_sensor_config;
  shared_mem_sensor_config.set_type(type);

  const std::string* name = GetValueAsString(config, "Name");
  if (name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Name field is not a string or missing");
  }
  shared_mem_sensor_config.set_name(*name);

  shared_mem_sensor_config.set_unit(ParseSensorUnit(config));

  absl::flat_hash_map<std::string, ThresholdConfigs> label_to_threshold_configs;
  ECCLESIA_ASSIGN_OR_RETURN(label_to_threshold_configs,
                            ParseThresholdConfigs(config));
  *shared_mem_sensor_config.mutable_thresholds() =
      label_to_threshold_configs[""];

  ECCLESIA_RETURN_IF_ERROR(
      ParseCommonEntityConfig(config, shared_mem_sensor_config));

  shared_mem_sensor_config.mutable_entity_common_config()->set_config_detected(
      is_detected);

  return shared_mem_sensor_config;
}

absl::StatusOr<IntelCpuSensorConfig>
EntityConfigJsonImpl::ParseIntelCpuSensorConfig(IntelCpuSensorType type,
                                                const nlohmann::json& config,
                                                bool is_detected) {
  if (type == INTEL_CPU_SENSOR_TYPE0_UNKNOWN) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a supported Intel CPU sensor type");
  }
  IntelCpuSensorConfig intel_cpu_sensor_config;
  intel_cpu_sensor_config.set_type(type);

  const std::string* name = GetValueAsString(config, "Name");
  if (name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Name field is not a string or missing");
  }
  intel_cpu_sensor_config.set_name(*name);

  ECCLESIA_ASSIGN_OR_RETURN(
      *intel_cpu_sensor_config.mutable_hal_common_config(),
      ParseHalCommonConfig(config));
  ECCLESIA_RETURN_IF_ERROR(
      ParseCommonEntityConfig(config, intel_cpu_sensor_config));

  ECCLESIA_ASSIGN_OR_RETURN(std::vector<std::string> labels,
                            ParseLabels(config));

  absl::flat_hash_map<std::string, std::string> label_to_name;
  ECCLESIA_ASSIGN_OR_RETURN(label_to_name,
                            ParseLabelToName(config, labels, true));
  intel_cpu_sensor_config.mutable_label_to_name()->insert(label_to_name.begin(),
                                                          label_to_name.end());

  intel_cpu_sensor_config.mutable_entity_common_config()->set_config_detected(
      is_detected);

  ECCLESIA_ASSIGN_OR_RETURN(uint64_t cpu_id, ParseCpuId(config));
  intel_cpu_sensor_config.set_cpu_id(cpu_id);

  // From
  // https://github.com/openbmc/dbus-sensors/blob/master/src/intel-cpu/IntelCPUSensorMain.cpp#L371
  if (std::optional<double> dts_offset =
          GetValueAsDoubleFromFloatOrInteger(config, kDtsOffsetKeyword);
      dts_offset.has_value()) {
    intel_cpu_sensor_config.set_dts_offset(*dts_offset);
  }

  const std::string* sensor_group =
      GetValueAsString(config, kSensorGroupKeyword);
  if (sensor_group != nullptr) {
    intel_cpu_sensor_config.set_sensor_group(*sensor_group);
  }

  return intel_cpu_sensor_config;
}

absl::StatusOr<VirtualSensorConfig>
EntityConfigJsonImpl::ParseVirtualSensorConfig(const nlohmann::json& config,
                                               bool is_detected) {
  VirtualSensorConfig virtual_sensor_config;
  const std::string* expression = GetValueAsString(config, "Expression");
  if (expression == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Expression field is not a string or missing");
  }
  virtual_sensor_config.set_expression(*expression);
  virtual_sensor_config.set_unit(ParseSensorUnit(config));
  virtual_sensor_config.mutable_entity_common_config()->set_config_detected(
      is_detected);

  absl::flat_hash_map<std::string, ThresholdConfigs> label_to_threshold_configs;
  ECCLESIA_ASSIGN_OR_RETURN(label_to_threshold_configs,
                            ParseThresholdConfigs(config));
  *virtual_sensor_config.mutable_thresholds() = label_to_threshold_configs[""];

  constexpr int kDefaultMaxVirtualSensorReading = 100;
  constexpr int kDefaultMinVirtualSensorReading = 0;
  ReadingRangeConfigs reading_range_configs = ParseReadingRangeConfigs(
      config, kDefaultMinVirtualSensorReading, kDefaultMaxVirtualSensorReading);
  *virtual_sensor_config.mutable_reading_ranges() = reading_range_configs;

  ECCLESIA_RETURN_IF_ERROR(
      ParseCommonEntityConfig(config, virtual_sensor_config));

  const std::string* name = GetValueAsString(config, "Name");
  if (name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Name field is not a string or missing");
  }
  virtual_sensor_config.set_name(*name);

  return virtual_sensor_config;
}

absl::Status EntityConfigJsonImpl::ParseFanConfig(
    EntityConfigJsonImplMutableData& mutable_data, const nlohmann::json& config,
    TopologyConfigNode& topology_config_node,
    std::string_view top_level_config_name) {
  const bool* tlbmc_owned = GetValueAsBool(config, "TlbmcOwned");
  // If not tlbmc owned then ignore
  if (tlbmc_owned == nullptr || !*tlbmc_owned) {
    return absl::OkStatus();
  }
  const std::string* type_str = GetValueAsString(config, "Type");
  if (type_str == nullptr || *type_str != kFanKeyword) {
    return absl::OkStatus();
  }

  const std::string* name = GetValueAsString(config, "Name");
  if (name == nullptr) {
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid config: Name field is not found for fan config: ",
                     config.dump()));
  }

  // LocationType and ServiceLabel are used for topology generation, so is
  // required
  const std::string* location_type = GetValueAsString(config, "LocationType");
  if (location_type == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: LocationType field is not found for fan config: ",
        config.dump()));
  }

  const std::string* service_label = GetValueAsString(config, "ServiceLabel");
  if (service_label == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: ServiceLabel field is not found for fan config: ",
        config.dump()));
  }

  const bool* is_hotpluggable = GetValueAsBool(config, "HotPluggable");
  if (is_hotpluggable == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: HotPluggable field is not found for fan config: ",
        config.dump()));
  }

  const std::string* pwm_sensor_name = GetValueAsString(config, "PWMSensor");
  if (pwm_sensor_name == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: PWMSensor field is not found for fan config: ",
        config.dump()));
  }

  const std::string* tach_sensor_name = GetValueAsString(config, "TachSensor");
  if (tach_sensor_name == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: TachSensor field is not found for fan config: ",
        config.dump()));
  }

  // Each fan should have a unique node name
  std::string fan_node_name =
      absl::StrFormat("%s_%s", top_level_config_name, *name);

  // Add fan to fru table.
  Fru fan_fru;
  fan_fru.mutable_data()->mutable_fan_info()->set_name(*name);
  const std::string* model = GetValueAsString(config, "Model");
  if (model != nullptr) {
    fan_fru.mutable_data()->mutable_fan_info()->set_model(*model);
  }
  fan_fru.mutable_data()->mutable_fan_info()->set_is_hotpluggable(
      *is_hotpluggable);
  fan_fru.mutable_data()->mutable_fan_info()->set_pwm_sensor_name(
      *pwm_sensor_name);
  fan_fru.mutable_data()->mutable_fan_info()->set_tach_sensor_name(
      *tach_sensor_name);

  fan_fru.mutable_attributes()->set_resource_type(RESOURCE_TYPE_FAN);
  fan_fru.mutable_attributes()->set_key(fan_node_name);
  fan_fru.mutable_attributes()->set_status(Status::STATUS_READY);
  fan_fru.mutable_attributes()->mutable_refresh_policy()->set_refresh_mode(
      RefreshMode::REFRESH_MODE_ON_DEMAND);

  // Fan should be its own Topology Node as it has its own machine level devpath
  TopologyConfigNode fan_node;
  fan_node.set_name(*name);
  fan_node.mutable_fru_info()->set_fru_key(fan_node_name);
  fan_node.set_config_key(fan_node_name);
  fan_node.mutable_location_context()->set_location_type(
      GetPartLocationTypeFromRedfishString(*location_type));

  // Add topology port configs for upstream and downstream
  PortConfig chassis_to_fan_port_config;
  chassis_to_fan_port_config.set_port_type(PORT_TYPE_DOWNSTREAM);
  chassis_to_fan_port_config.set_port_name(fan_node_name);
  chassis_to_fan_port_config.set_port_label(*service_label);
  topology_config_node.mutable_port_configs()->insert(
      {fan_node_name, std::move(chassis_to_fan_port_config)});

  PortConfig fan_to_chassis_port_config;
  fan_to_chassis_port_config.set_port_type(PORT_TYPE_UPSTREAM);
  fan_to_chassis_port_config.set_port_name(fan_node_name);
  *fan_node.add_upstream_port_configs() = std::move(fan_to_chassis_port_config);

  // The config name and the fru key are identical.
  mutable_data.topology_config.mutable_topology_config_nodes()->insert(
      {fan_node_name, std::move(fan_node)});
  mutable_data.topology_config.mutable_fru_configs()->insert(
      {fan_node_name, fan_node_name});
  mutable_data.fru_table.mutable_key_to_fru()->insert(
      {fan_node_name, std::move(fan_fru)});

  return absl::OkStatus();
}

absl::StatusOr<NicTelemetryConfig>
EntityConfigJsonImpl::ParseNicTelemetryConfig(const nlohmann::json& config,
                                              bool is_detected) {
  NicTelemetryConfig nic_telemetry_config;
  std::optional<uint64_t> bus =
      GetValueAsUintFromStringOrInteger(config, "Bus");
  if (!bus.has_value()) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: element does not have a Bus field: ", config.dump()));
  }
  nic_telemetry_config.mutable_hal_common_config()->set_bus(*bus);

  const std::string* version = GetValueAsString(config, "Version");
  if (version == nullptr) {
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid config: element does not have a Version field: ",
                     config.dump()));
  }
  if (*version == "v1" || *version == "V1") {
    nic_telemetry_config.set_version(nic_veeprom::NIC_TELEMETRY_VERSION_V1);
  } else if (*version == "v2" || *version == "V2") {
    nic_telemetry_config.set_version(nic_veeprom::NIC_TELEMETRY_VERSION_V2);
  } else {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: element does not have a supported Version field: ",
        config.dump()));
  }
  std::vector<nic_veeprom::NicTelemetryName> telemetry_names;
  ECCLESIA_ASSIGN_OR_RETURN(telemetry_names, ParseNicTelemetryNames(config));
  for (const auto& telemetry_name : telemetry_names) {
    nic_telemetry_config.add_telemetry_names(telemetry_name);
  }

  nic_telemetry_config.mutable_entity_common_config()->set_config_detected(
      is_detected);
  return nic_telemetry_config;
}

absl::Status EntityConfigJsonImpl::ParseProcessorConfig(
    EntityConfigJsonImplMutableData& mutable_data, const nlohmann::json& config,
    TopologyConfigNode& topology_config_node,
    std::string_view top_level_config_name) {
  const std::string* type_str = GetValueAsString(config, "Type");
  const bool* tlbmc_owned = GetValueAsBool(config, "TlbmcOwned");
  IntelCpuSensorType intel_cpu_sensor_type = INTEL_CPU_SENSOR_TYPE0_UNKNOWN;
  if (tlbmc_owned != nullptr && *tlbmc_owned) {
    intel_cpu_sensor_type = IsIntelCpuSensor(*type_str);
  }
  if (type_str == nullptr ||
      (intel_cpu_sensor_type == INTEL_CPU_SENSOR_TYPE0_UNKNOWN &&
       *type_str != kProcessorKeyword)) {
    return absl::OkStatus();
  }

  const std::string* processor_id = GetValueAsString(config, "Name");
  if (processor_id == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Name field is not found for processor config");
  }

  // Each processor should have a unique node name
  std::string processor_node_name =
      absl::StrFormat("%s_%s", top_level_config_name, *processor_id);

  // Add processor to fru table.
  Fru processor_fru;
  processor_fru.mutable_attributes()->set_resource_type(
      RESOURCE_TYPE_PROCESSOR);
  processor_fru.mutable_attributes()->set_key(processor_node_name);
  processor_fru.mutable_attributes()->set_status(Status::STATUS_READY);

  // Processor should be its own Topology Node as it has its own machine level
  // devpath
  TopologyConfigNode processor_node;
  processor_node.set_name(*processor_id);
  processor_node.mutable_fru_info()->set_fru_key(processor_node_name);
  processor_node.set_config_key(processor_node_name);

  // Add topology port configs for upstream and downstream
  PortConfig chassis_to_processor_port_config;
  chassis_to_processor_port_config.set_port_type(PORT_TYPE_DOWNSTREAM);
  chassis_to_processor_port_config.set_port_name(processor_node_name);
  chassis_to_processor_port_config.set_port_label(
      absl::AsciiStrToUpper(*processor_id));
  topology_config_node.mutable_port_configs()->insert(
      {processor_node_name, std::move(chassis_to_processor_port_config)});

  PortConfig processor_to_chassis_port_config;
  processor_to_chassis_port_config.set_port_type(PORT_TYPE_UPSTREAM);
  processor_to_chassis_port_config.set_port_name(processor_node_name);
  *processor_node.add_upstream_port_configs() =
      std::move(processor_to_chassis_port_config);

  // The config name and the fru key are identical.
  mutable_data.topology_config.mutable_topology_config_nodes()->insert(
      {processor_node_name, std::move(processor_node)});
  mutable_data.topology_config.mutable_fru_configs()->insert(
      {processor_node_name, processor_node_name});
  mutable_data.fru_table.mutable_key_to_fru()->insert(
      {processor_node_name, std::move(processor_fru)});

  return absl::OkStatus();
}

absl::Status EntityConfigJsonImpl::ParseDimmConfig(
    EntityConfigJsonImplMutableData& mutable_data, const nlohmann::json& config,
    TopologyConfigNode& topology_config_node,
    std::string_view top_level_config_name) {
  const bool* tlbmc_owned = GetValueAsBool(config, "TlbmcOwned");
  // If not tlbmc owned then ignore
  if (tlbmc_owned == nullptr || !*tlbmc_owned) {
    return absl::OkStatus();
  }
  const std::string* type_str = GetValueAsString(config, "Type");
  if (type_str == nullptr || *type_str != kDimmKeyword) {
    return absl::OkStatus();
  }

  const std::string* dimm_name = GetValueAsString(config, "Name");
  if (dimm_name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Name field is not found for dimm config");
  }

  const std::string* service_label = GetValueAsString(config, "ServiceLabel");
  if (service_label == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: ServiceLabel field is not found for dimm config");
  }

  // Each dimm should have a unique node name
  std::string dimm_node_name =
      absl::StrFormat("%s_%s", top_level_config_name, *dimm_name);

  // Add dimm to fru table.
  Fru dimm_fru;
  dimm_fru.mutable_attributes()->set_resource_type(RESOURCE_TYPE_DIMM);
  dimm_fru.mutable_attributes()->set_key(dimm_node_name);
  dimm_fru.mutable_attributes()->set_status(Status::STATUS_READY);

  // Dimm should be its own Topology Node as it has its own machine level
  // devpath
  TopologyConfigNode dimm_node;
  dimm_node.set_name(*dimm_name);
  dimm_node.mutable_fru_info()->set_fru_key(dimm_node_name);
  dimm_node.set_config_key(dimm_node_name);

  // Add topology port configs for upstream and downstream
  PortConfig chassis_to_dimm_port_config;
  chassis_to_dimm_port_config.set_port_type(PORT_TYPE_DOWNSTREAM);
  chassis_to_dimm_port_config.set_port_name(dimm_node_name);
  chassis_to_dimm_port_config.set_port_label(*service_label);
  topology_config_node.mutable_port_configs()->insert(
      {dimm_node_name, std::move(chassis_to_dimm_port_config)});

  PortConfig dimm_to_chassis_port_config;
  dimm_to_chassis_port_config.set_port_type(PORT_TYPE_UPSTREAM);
  dimm_to_chassis_port_config.set_port_name(dimm_node_name);
  *dimm_node.add_upstream_port_configs() =
      std::move(dimm_to_chassis_port_config);

  // The config name and the fru key are identical.
  mutable_data.topology_config.mutable_topology_config_nodes()->insert(
      {dimm_node_name, std::move(dimm_node)});
  mutable_data.topology_config.mutable_fru_configs()->insert(
      {dimm_node_name, dimm_node_name});
  mutable_data.fru_table.mutable_key_to_fru()->insert(
      {dimm_node_name, std::move(dimm_fru)});

  return absl::OkStatus();
}

absl::Status EntityConfigJsonImpl::LinkParentChildNodes(
    Fru& current_fru, TopologyConfigNode& current_node, Fru& downstream_fru,
    TopologyConfigNode& downstream_node) {
  // Link current node -> downstream node.
  if (downstream_fru.attributes().resource_type() == RESOURCE_TYPE_BOARD) {
    current_node.add_children_chassis_ids(downstream_node.name());
  } else if (downstream_fru.attributes().resource_type() ==
             RESOURCE_TYPE_ASSEMBLY) {
    current_node.add_children_assembly_ids(downstream_node.name());
  } else if (downstream_fru.attributes().resource_type() ==
             RESOURCE_TYPE_CABLE) {
    if (current_fru.attributes().resource_type() == RESOURCE_TYPE_CABLE) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid config: Cable cannot be connected to another cable.",
          current_node.name(), " -> ", downstream_node.name()));
    }
    current_node.add_children_cable_ids(downstream_node.name());
  } else if (downstream_fru.attributes().resource_type() == RESOURCE_TYPE_FAN) {
    current_node.mutable_children_fans()->insert(
        {downstream_node.name(), downstream_node.config_key()});
  } else if (downstream_fru.attributes().resource_type() ==
             RESOURCE_TYPE_PROCESSOR) {
    current_node.mutable_children_processors()->insert(
        {downstream_node.name(), downstream_node.config_key()});
  } else if (downstream_fru.attributes().resource_type() ==
             RESOURCE_TYPE_DIMM) {
    current_node.mutable_children_dimms()->insert(
        {downstream_node.name(), downstream_node.config_key()});
  }

  // Link current node <- downstream node.
  if (current_fru.attributes().resource_type() == RESOURCE_TYPE_BOARD) {
    // Only cable can have multiple upstream boards for now.
    if (downstream_fru.attributes().resource_type() != RESOURCE_TYPE_CABLE &&
        !downstream_node.parent_chassis_ids().empty()) {
      return absl::InternalError(
          absl::StrCat("Invalid config: ", downstream_node.name(),
                       " has more than one parent chassis, which is not "
                       "expected."));
    }
    downstream_node.set_parent_resource_id(current_node.name());
    downstream_node.add_parent_chassis_ids(current_node.name());
  } else if (current_fru.attributes().resource_type() == RESOURCE_TYPE_CABLE) {
    downstream_node.add_parent_cable_ids(current_node.name());
  }

  return absl::OkStatus();
}

absl::Status EntityConfigJsonImpl::CreateAssociationsBetweenTopologyConfigNodes(
    TopologyConfig& topology_config, FruTable& fru_table,
    absl::flat_hash_set<absl::string_view>& expected_nodes_traversed) {
  if (topology_config.topology_config_nodes().empty()) {
    return absl::InternalError(
        "Internal error: Somehow topology config is empty. You may need to add "
        "ports to the EM Configs.");
  }

  // Find root node in TopologyConfig.
  std::string root_chassis_location_code;
  for (const auto& [config_key, topology_config_node] :
       topology_config.topology_config_nodes()) {
    // There are multiple inconsistent root chassis location codes found in the
    // configs. Stop the topology buildup with an error.
    if (!root_chassis_location_code.empty() &&
        topology_config_node.has_root_chassis_location_code()) {
      return absl::InternalError(
          absl::StrFormat("Invalid config: Multiple root chassis location "
                          "codes found! Previous: %s. Current: %s",
                          root_chassis_location_code,
                          topology_config_node.root_chassis_location_code()));
    }
    if (topology_config_node.has_root_chassis_location_code()) {
      root_chassis_location_code =
          topology_config_node.root_chassis_location_code();
    }
    if (topology_config_node.upstream_port_configs().empty()) {
      if (topology_config.has_root_node_key()) {
        return absl::InternalError("Invalid config: Multiple root nodes found");
      }
      topology_config.set_root_node_key(config_key);
    }
  }

  if (!topology_config.has_root_node_key()) {
    return absl::InternalError("Invalid config: No root node found");
  }

  // Map of port name to config key.
  absl::flat_hash_map<std::string, std::string>
      upstream_port_name_to_config_key;
  for (const auto& [config_key, topology_config_node] :
       topology_config.topology_config_nodes()) {
    for (const auto& upstream_port_config :
         topology_config_node.upstream_port_configs()) {
      if (!upstream_port_config.port_name().empty()) {
        upstream_port_name_to_config_key[upstream_port_config.port_name()] =
            config_key;
      }
    }
  }

  // Derive devpath for each topology config node.
  // Not checking for presence of root node since it is already checked above.
  TopologyConfigNode& root_node =
      topology_config.mutable_topology_config_nodes()->at(
          topology_config.root_node_key());
  root_node.mutable_location_context()->set_devpath(absl::StrCat(
      "/", (root_chassis_location_code.empty()
                ? "phys"
                : root_node.root_chassis_location_code().c_str())));
  LOG(INFO) << "Final root devpath: " << root_node.location_context().devpath();

  // Compare with the node names to ensure the devpath is the alphabetically
  // smallest.
  std::priority_queue<TopologyConfigNode*, std::vector<TopologyConfigNode*>,
                      TopologyConfigNodePtrComparator>
      node_queue;
  node_queue.push(&root_node);
  absl::flat_hash_set<absl::string_view> nodes_traversed;
  while (!node_queue.empty()) {
    TopologyConfigNode* current_node = node_queue.top();
    node_queue.pop();

    // Always populate root chassis location code for all nodes.
    current_node->set_root_chassis_location_code(root_chassis_location_code);

    nodes_traversed.insert(current_node->config_key());
    auto find_current_fru = fru_table.mutable_key_to_fru()->find(
        current_node->fru_info().fru_key());
    if (find_current_fru == fru_table.key_to_fru().end()) {
      LOG(WARNING) << "FRU not found for key while setting devpath: "
                   << current_node->fru_info().fru_key()
                   << ". This is normally not expected. Check debug endpoint "
                      "and reproduce the issue.";
      continue;
    }
    Fru& current_fru = find_current_fru->second;
    for (const auto& [port_name, port_config] : current_node->port_configs()) {
      auto find_downstream_node_key_it =
          upstream_port_name_to_config_key.find(port_name);
      if (find_downstream_node_key_it ==
          upstream_port_name_to_config_key.end()) {
        continue;
      }
      absl::string_view downstream_node_key =
          find_downstream_node_key_it->second;
      // Downstream node is always present in the topology config so will not
      // check for presence.
      TopologyConfigNode& downstream_node =
          topology_config.mutable_topology_config_nodes()->at(
              downstream_node_key);
      // Downstream node key is always present in the FRU table so will not
      // check for presence.
      Fru& downstream_fru = fru_table.mutable_key_to_fru()->at(
          downstream_node.fru_info().fru_key());

      absl::Status status = LinkParentChildNodes(
          current_fru, *current_node, downstream_fru, downstream_node);
      if (!status.ok()) {
        return status;
      }

      // If the downstream node has a devpath, then we can skip the devpath
      // generation logic below and does not need to push it onto the queue
      // again.
      if (downstream_node.has_location_context() &&
          downstream_node.location_context().has_devpath()) {
        continue;
      }
      // If node is Sub-Fru then we add :device to the devpath and then append
      // the port label.
      if (port_config.port_label() != kDontSetDevpathKeyword) {
        if (downstream_node.fru_info().is_sub_fru() ||
            downstream_node.location_context().location_type() ==
                PART_LOCATION_TYPE_EMBEDDED) {
          downstream_node.mutable_location_context()->set_devpath(
              absl::StrCat(current_node->mutable_location_context()->devpath(),
                           ":device:", port_config.port_label()));
        } else {
          downstream_node.mutable_location_context()->set_devpath(
              absl::StrCat(current_node->mutable_location_context()->devpath(),
                           "/", port_config.port_label()));
        }
      }
      node_queue.push(&downstream_node);
    }
  }

  if (expected_nodes_traversed != nodes_traversed) {
    std::vector<absl::string_view> missing_nodes;
    for (const auto& node : expected_nodes_traversed) {
      if (nodes_traversed.find(node) == nodes_traversed.end()) {
        missing_nodes.push_back(node);
      }
    }
    std::vector<absl::string_view> unexpected_nodes;
    for (const auto& node : nodes_traversed) {
      if (expected_nodes_traversed.find(node) ==
          expected_nodes_traversed.end()) {
        unexpected_nodes.push_back(node);
      }
    }
    return absl::InternalError(absl::Substitute(
        "The following FRUs are not connected to the topology: $0, which "
        "means the config in this machine is not fully tested by tlBMC. The "
        "following FRUs were found in the topology, but not expected: $1",
        absl::StrJoin(missing_nodes, ", "),
        absl::StrJoin(unexpected_nodes, ", ")));
  }
  return absl::OkStatus();
}

absl::StatusOr<const TopologyConfigNode*> EntityConfigJsonImpl::GetFruTopology(
    absl::string_view fru_key) const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  const auto fru_config_it = topology_config->fru_configs().find(fru_key);
  if (fru_config_it == topology_config->fru_configs().end()) {
    return absl::NotFoundError(absl::StrCat("FRU key not found: ", fru_key));
  }
  return &(topology_config->topology_config_nodes().at(fru_config_it->second));
}

absl::StatusOr<const TopologyConfigNode*>
EntityConfigJsonImpl::GetFruTopologyByConfig(
    absl::string_view config_key) const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  const auto fru_config_it =
      topology_config->topology_config_nodes().find(config_key);
  if (fru_config_it == topology_config->topology_config_nodes().end()) {
    return absl::NotFoundError(
        absl::StrCat("config key not found: ", config_key));
  }
  return &(fru_config_it->second);
}

absl::StatusOr<const TopologyConfig*> EntityConfigJsonImpl::GetTopologyConfig()
    const {
  ECCLESIA_RETURN_IF_ERROR(GetParsedStatus());

  return &data_store_.mutable_data.Get()->topology_config;
}

absl::StatusOr<std::vector<std::string>>
EntityConfigJsonImpl::GetAllConfigKeys() const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  std::vector<std::string> config_keys;
  for (const auto& [config_key, topology_config_node] :
       topology_config->topology_config_nodes()) {
    if (!topology_config_node.not_owned_by_tlbmc()) {
      config_keys.push_back(config_key);
    }
  }
  std::sort(config_keys.begin(), config_keys.end());
  return config_keys;
}

absl::StatusOr<std::string> EntityConfigJsonImpl::GetConfigKeyByFruKey(
    absl::string_view fru_key) const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  auto fru_config_it = topology_config->fru_configs().find(fru_key);
  if (fru_config_it == topology_config->fru_configs().end()) {
    return absl::NotFoundError(absl::StrCat("FRU key not found: ", fru_key));
  }
  return fru_config_it->second;
}

absl::StatusOr<std::string> EntityConfigJsonImpl::GetFruKeyByConfigKey(
    absl::string_view config_key) const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  auto fru_config_it =
      topology_config->topology_config_nodes().find(config_key);
  if (fru_config_it == topology_config->topology_config_nodes().end()) {
    return absl::NotFoundError(
        absl::StrCat("config key not found: ", config_key));
  }
  return fru_config_it->second.fru_info().fru_key();
}

absl::StatusOr<std::vector<std::pair<std::string, std::string>>>
EntityConfigJsonImpl::GetFanInfoByConfigKey(
    absl::string_view config_key) const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  auto config_it = topology_config->topology_config_nodes().find(config_key);
  if (config_it == topology_config->topology_config_nodes().end()) {
    return absl::NotFoundError(
        absl::StrCat("config key not found: ", config_key));
  }
  std::vector<std::pair<std::string, std::string>> fan_info;
  for (const auto& [fan_id, fan_key] : config_it->second.children_fans()) {
    fan_info.push_back(std::make_pair(fan_id, fan_key));
  }
  return fan_info;
}

absl::StatusOr<const Fru*> EntityConfigJsonImpl::GetFru(
    absl::string_view key) const {
  ECCLESIA_ASSIGN_OR_RETURN(const FruTable* fru_table, GetAllFrus());
  auto it = fru_table->key_to_fru().find(key);
  if (it == fru_table->key_to_fru().end()) {
    return absl::NotFoundError(absl::StrCat("FRU key not found: ", key));
  }
  return &it->second;
}

absl::StatusOr<const FruTable*> EntityConfigJsonImpl::GetAllFrus() const {
  ECCLESIA_RETURN_IF_ERROR(GetParsedStatus());

  return &data_store_.mutable_data.Get()->fru_table;
}

absl::StatusOr<std::string> EntityConfigJsonImpl::GetFruDevpath(
    absl::string_view fru_key) const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  auto fru_config_it = topology_config->fru_configs().find(fru_key);
  if (fru_config_it == topology_config->fru_configs().end()) {
    return absl::NotFoundError(absl::StrCat("FRU key not found: ", fru_key));
  }
  return topology_config->topology_config_nodes()
      .at(fru_config_it->second)
      .location_context()
      .devpath();
}

nlohmann::json EntityConfigJsonImpl::ToJson() const {
  nlohmann::json json;
  json["HwmonTempSensorConfigs"] = nlohmann::json::array();
  for (const auto& hwmon_temp_sensor_config :
       data_store_.immutable_data.hwmon_temp_sensor_configs) {
    json["HwmonTempSensorConfigs"].push_back(
        ProtoToJson(hwmon_temp_sensor_config));
  }

  json["PsuSensorConfigs"] = nlohmann::json::array();
  for (const auto& psu_sensor_config :
       data_store_.immutable_data.psu_sensor_configs) {
    json["PsuSensorConfigs"].push_back(ProtoToJson(psu_sensor_config));
  }

  json["FanControllerConfigs"] = nlohmann::json::array();
  for (const auto& fan_controller_config :
       data_store_.immutable_data.fan_controller_configs) {
    json["FanControllerConfigs"].push_back(ProtoToJson(fan_controller_config));
  }

  json["FanPwmConfigs"] = nlohmann::json::array();
  for (const auto& fan_pwm_config :
       data_store_.immutable_data.fan_pwm_configs) {
    json["FanPwmConfigs"].push_back(ProtoToJson(fan_pwm_config));
  }

  json["FanTachConfigs"] = nlohmann::json::array();
  for (const auto& fan_tach_config :
       data_store_.immutable_data.fan_tach_configs) {
    json["FanTachConfigs"].push_back(ProtoToJson(fan_tach_config));
  }

  json["SharedMemSensorConfigs"] = nlohmann::json::array();
  for (const auto& shared_mem_sensor_config :
       data_store_.immutable_data.shared_mem_sensor_configs) {
    json["SharedMemSensorConfigs"].push_back(
        ProtoToJson(shared_mem_sensor_config));
  }

  json["IntelCpuSensorConfigs"] = nlohmann::json::array();
  for (const auto& intel_cpu_sensor_config :
       data_store_.immutable_data.intel_cpu_sensor_configs) {
    json["IntelCpuSensorConfigs"].push_back(
        ProtoToJson(intel_cpu_sensor_config));
  }

  json["VirtualSensorConfigs"] = nlohmann::json::array();
  for (const auto& virtual_sensor_config :
       data_store_.immutable_data.virtual_sensor_configs) {
    json["VirtualSensorConfigs"].push_back(ProtoToJson(virtual_sensor_config));
  }

  const EntityConfigJsonImplMutableData* mutable_data =
      data_store_.mutable_data.Get();

  if (mutable_data != nullptr) {
    json["TopologyConfig"] = ProtoToJson(mutable_data->topology_config);
    json["FruTable"] = ProtoToJson(mutable_data->fru_table);
  }

  json["CurrentStatus"] = mutable_data->parsed_status.ToString();

  return json;
}

EntityConfigJsonImpl::EntityConfigJsonImpl(
    std::vector<nlohmann::json>&& config_list, const RawFruTable& fru_table,
    size_t ad_hoc_fru_count)
    : immutable_config_list_(std::move(config_list)),
      data_store_(PackDataIntoStore(
          ReloadConfig(fru_table, ad_hoc_fru_count, ReloadType::kReloadAll))) {}

absl::StatusOr<std::unique_ptr<EntityConfig>> EntityConfigJsonImpl::Create(
    std::vector<nlohmann::json>&& config_list, const RawFruTable& fru_table,
    size_t ad_hoc_fru_count) {
  auto entity_config = absl::WrapUnique(new EntityConfigJsonImpl(
      std::move(config_list), fru_table, ad_hoc_fru_count));
  ECCLESIA_RETURN_IF_ERROR(entity_config->GetParsedStatus());
  return entity_config;
}

absl::StatusOr<std::vector<nlohmann::json>>
EntityConfigJsonImpl::ParseJsonFilesIntoConfigList(
    absl::string_view config_location) {
  std::vector<nlohmann::json> config_list;
  if (!std::filesystem::exists(config_location)) {
    return config_list;
  }
  for (const auto& entry :
       std::filesystem::directory_iterator(config_location)) {
    if (entry.is_regular_file() && entry.path().extension() == ".json") {
      std::string json_file_path = entry.path().string();
      std::ifstream json_file(json_file_path);
      if (!json_file.is_open()) {
        return absl::InternalError(
            absl::StrCat("Failed to open file: ", json_file_path));
      }

      nlohmann::json parsed_config =
          nlohmann::json::parse(json_file, nullptr, /*allow_exceptions=*/false,
                                /*ignore_comments=*/true);
      if (parsed_config.is_discarded()) {
        return absl::InvalidArgumentError(
            absl::StrCat(json_file_path, " is illformed."));
      }
      nlohmann::json::array_t config_as_array;
      if (parsed_config.is_array()) {
        config_as_array = parsed_config.get<nlohmann::json::array_t>();
      } else {
        config_as_array.push_back(parsed_config);
      }

      for (const auto& config : config_as_array) {
        config_list.push_back(config);
      }
    }
  }
  return config_list;
}

void EntityConfigJsonImpl::SetSmartRouter(RouterInterface* smart_router) {
  smart_router_ = smart_router;
}

void EntityConfigJsonImpl::SetSensorCollector(
    SensorCollector* sensor_collector) {
  sensor_collector_ = sensor_collector;
}

absl::Status EntityConfigJsonImpl::GetParsedStatus() const {
  return data_store_.mutable_data.Get()->parsed_status;
}

EntityConfigJsonImplDataStore EntityConfigJsonImpl::PackDataIntoStore(
    EntityConfigJsonImplData&& data) {
  return EntityConfigJsonImplDataStore{
      .immutable_data = std::move(data.immutable_data),
      .mutable_data = SimpleRcu<EntityConfigJsonImplMutableData>(
          std::move(data.mutable_data), data.max_updates_to_mutable_data)};
}

}  // namespace milotic_tlbmc
