#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 =
      GetValueAsJson(config, kStorageKeyword);
  if (storage_config == nullptr) {
    return absl::OkStatus();
  }
  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, 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()) {
      bool i2c_info_matches_or_null =
          CheckI2cInfoMatchOrNull(bus, address, fru);

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

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

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

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

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

  return false;
}

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

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

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

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

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

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

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

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

}  // namespace

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return absl::OkStatus();
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  ECCLESIA_RETURN_IF_ERROR(
      ParseCommonEntityConfig(config, hwmon_temp_sensor_config));

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

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

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

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

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

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

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

  return hwmon_temp_sensor_config;
}

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

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

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

  return fan_controller_config;
}

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

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

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

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

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

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

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

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

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

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

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

  return psu_sensor_config;
}

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

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

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

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

  ECCLESIA_RETURN_IF_ERROR(ParseCommonEntityConfig(config, fan_pwm_config));

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

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

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

  return fan_pwm_config;
}

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

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

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

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

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

  ECCLESIA_RETURN_IF_ERROR(ParseCommonEntityConfig(config, fan_tach_config));

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

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

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

  return fan_tach_config;
}

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

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

  shared_mem_sensor_config.set_unit(ParseSensorUnit(config));

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

  ECCLESIA_RETURN_IF_ERROR(
      ParseCommonEntityConfig(config, shared_mem_sensor_config));

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

  return shared_mem_sensor_config;
}

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

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

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

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

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

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

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

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

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

  return intel_cpu_sensor_config;
}

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

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

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

  ECCLESIA_RETURN_IF_ERROR(
      ParseCommonEntityConfig(config, virtual_sensor_config));

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

  return virtual_sensor_config;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  return absl::OkStatus();
}

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

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

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

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

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

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

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

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

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

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

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

  return absl::OkStatus();
}

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

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

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

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

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

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

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

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

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

  return absl::OkStatus();
}

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

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

  return absl::OkStatus();
}

absl::Status EntityConfigJsonImpl::ValidateTopology(
    const absl::flat_hash_set<absl::string_view>& expected_nodes_traversed,
    const absl::flat_hash_set<absl::string_view>& nodes_traversed) {
  if (expected_nodes_traversed != nodes_traversed) {
    // Since the BFS through the topology will validate every fru key, if we
    // traverse through more nodes than expected, that means there are multiple
    // configs probing the same fru key.
    if (GetTlbmcConfig()
            .fru_collector_module()
            .multiple_configs_probe_raw_fru() &&
        nodes_traversed.size() > expected_nodes_traversed.size()) {
      return absl::OkStatus();
    }

    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::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);
    }
  }
  return ValidateTopology(expected_nodes_traversed, nodes_traversed);
}

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
