#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 or $bus 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") &&
          !absl::StrContainsIgnoreCase(name, "$bus")) {
        return absl::InvalidArgumentError(
            absl::StrCat("Invalid config: Frus match the same config multiple"
                         " times but config name does not contain $index or "
                         "$bus: ",
                         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;
}

bool EntityConfigJsonImpl::IsRedfishRouteConfig(std::string_view type) {
  return type == "RedfishRoute";
}

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;
}

bool EntityConfigJsonImpl::IsConfigKeyOwningAllSensors(
    absl::string_view config_key) const {
  return data_store_.immutable_data.redfish_route_configs
      .configs_owning_sensors_collection.contains(config_key);
}

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 (IsRedfishRouteConfig(*type)) {
    tlbmc_supported = true;
    const bool* owns_sensor_collection =
        GetValueAsBool(element, "OwnsSensorsCollection");
    if (owns_sensor_collection != nullptr && *owns_sensor_collection) {
      data.redfish_route_configs.configs_owning_sensors_collection.insert(
          std::string(config_name_with_index));
    }
  }

  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);
      absl::StrReplaceAll(
          {{"$BUS", std::to_string(config_data.fru_keys[i].bus)}},
          &config_name_with_index);
      absl::StrReplaceAll(
          {{"$bus", std::to_string(config_data.fru_keys[i].bus)}},
          &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
