#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 <tuple>
#include <utility>
#include <vector>

#include "one/public_offline_node_entities.h"
#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.hpp"
#include "nlohmann/json_fwd.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 "gpio_sensor_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 "redfish_aggregated_sensor_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 "google/protobuf/descriptor.h"
#include "re2/re2.h"

namespace milotic_tlbmc {

using ::production_msv::node_entities::ReadOfflineNodeEntityInformation;
using ::production_msv::node_entities_proto::OfflineNodeEntityInformation;

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;
using ::google::protobuf::Descriptor;
using ::google::protobuf::FieldDescriptor;
using ::google::protobuf::Message;
using ::google::protobuf::Reflection;

// 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";
constexpr absl::string_view kPowerSupplyDownstreamKeyword =
    "PowerSupplyPortDownstream";
constexpr absl::string_view kPowerSupplyUpstreamKeyword =
    "PowerSupplyPortUpstream";
// 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 kNotProbePrefix = "NOT(";
constexpr absl::string_view kOfflineNodeEntityInfoKeyword =
    "OFFLINE_NODE_ENTITY_INFO";

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 kManagerKeyword = "Manager";
constexpr absl::string_view kComputerSystemKeyword = "ComputerSystem";
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>, 9>
    kSupportedSensorUnits = {{
        // go/keep-sorted start
        {"Ampere", SensorUnit::UNIT_AMPERE},
        {"Count", SensorUnit::UNIT_COUNT},
        {"DegreeCelsius", SensorUnit::UNIT_DEGREE_CELSIUS},
        {"Joule", SensorUnit::UNIT_JOULES},
        {"Pa", SensorUnit::UNIT_PASCAL},
        {"Percent", SensorUnit::UNIT_PERCENT},
        {"RPM", SensorUnit::UNIT_REVOLUTION_PER_MINUTE},
        {"Volt", SensorUnit::UNIT_VOLT},
        {"Watt", SensorUnit::UNIT_WATT},
        // go/keep-sorted end
    }};

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

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

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

  return absl::OkStatus();
}

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

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

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

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

absl::Status ParsePowerPortConfig(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 != kPowerSupplyUpstreamKeyword &&
       *port_type_str != kPowerSupplyDownstreamKeyword)) {
    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 or valid for port");
  }

  PortConfig port_config;
  port_config.set_port_name(*port_name);
  if (*port_type_str == kPowerSupplyUpstreamKeyword) {
    if (std::any_of(topology_config_node.upstream_power_port_configs().cbegin(),
                    topology_config_node.upstream_power_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 Power connection "
                       "configs present for ",
                       *port_name));
    }
    port_config.set_port_type(PORT_TYPE_POWER_UPSTREAM);
    *topology_config_node.add_upstream_power_port_configs() =
        std::move(port_config);
  } else if (*port_type_str == kPowerSupplyDownstreamKeyword) {
    port_config.set_port_type(PORT_TYPE_POWER_DOWNSTREAM);
    topology_config_node.mutable_power_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::StatusOr<absl::flat_hash_map<std::string, RelatedItem>>
ParseRelatedItemMap(const nlohmann::json& config) {
  absl::flat_hash_map<std::string, RelatedItem> sensor_name_to_related_item;
  if (!config.contains(kRelatedItemKeyword)) {
    return sensor_name_to_related_item;
  }
  const nlohmann::json::array_t* related_item_configs =
      GetValueAsArray(config, kRelatedItemKeyword);
  if (related_item_configs == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: RelatedItem field is not an array");
  }

  for (const auto& related_item_config : *related_item_configs) {
    const std::string* sensor_name =
        GetValueAsString(related_item_config, "SensorName");
    if (sensor_name == nullptr) {
      return absl::InvalidArgumentError(
          absl::StrCat("Invalid RelatedItem config: SensorName field is not a "
                       "string or missing "
                       "for related item config: ",
                       related_item_config.dump()));
    }

    const std::string* resource_id =
        GetValueAsString(related_item_config, "ResourceId");
    if (resource_id == nullptr) {
      return absl::InvalidArgumentError(
          absl::StrCat("Invalid RelatedItem config: No ResourceId found for "
                       "related item config: ",
                       related_item_config.dump()));
    }
    const std::string* item_type_str =
        GetValueAsString(related_item_config, "Type");
    ResourceType resource_type;
    if (item_type_str == nullptr ||
        !ResourceType_Parse(*item_type_str, &resource_type)) {
      return absl::InvalidArgumentError(
          absl::StrCat("Invalid RelatedItem config: Invalid Type "
                       "found for config: ",
                       related_item_config.dump()));
    }
    RelatedItem related_item;
    related_item.set_id(*resource_id);
    related_item.set_type(resource_type);
    sensor_name_to_related_item[*sensor_name] = related_item;
  }
  return sensor_name_to_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::Status ParsePowerSupplyConfig(const nlohmann::json& config,
                                    Fru& fru_object) {
  const nlohmann::json* power_supply_config_ptr =
      GetValueAsJson(config, "PowerSupply");
  if (power_supply_config_ptr == nullptr) {
    return absl::OkStatus();
  }

  PowerSupplyInfo power_supply_info;
  nlohmann::json power_supply_config = *power_supply_config_ptr;

  const std::string* input_sensor_name_ptr =
      GetValueAsString(power_supply_config, "InputSensorName");
  if (input_sensor_name_ptr == nullptr) {
    return absl::InvalidArgumentError(
        absl::StrCat("Invalid PowerSupply config: InputSensorName field is not "
                     "a string or missing for power supply config: ",
                     power_supply_config.dump()));
  }

  power_supply_info.set_input_sensor_name(*input_sensor_name_ptr);
  *fru_object.mutable_data()->mutable_power_supply_info() = power_supply_info;

  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 EvaluateProbeRegexMatch(const std::string& fru_field,
                             const std::string& probe_field) {
  if (absl::StartsWith(probe_field, kNotProbePrefix) &&
      absl::EndsWith(probe_field, ")")) {
    return !RE2::FullMatch(
        fru_field,
        probe_field.substr(kNotProbePrefix.size(),
                           probe_field.size() - (kNotProbePrefix.size() + 1)));
  }
  return RE2::FullMatch(fru_field, probe_field);
}

absl::StatusOr<bool> CheckOfflineNodeEntityInfoMatch(
    const nlohmann::json& one_probe_config,
    const Message& offline_node_entities) {
  const Descriptor* descriptor = offline_node_entities.GetDescriptor();
  const Reflection* reflection = offline_node_entities.GetReflection();

  // To enforce AND behavior for all regex fields defined in this ONE Probe
  // config, we must iterate over all json fields, return false early if we know
  // that the regex fields do not match.
  for (auto const& [key, value] : one_probe_config.items()) {
    const FieldDescriptor* field = descriptor->FindFieldByName(key);

    if (field == nullptr) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid config: '", key,
          "' field is not found at this level in OfflineNodeEntities"));
    }

    // If the value is an object, we need to check if the field is a message
    // in OfflineNodeEntities. If it is, then we need to recursively check the
    // equality of the two fields.
    if (value.is_object()) {
      if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
        return absl::InvalidArgumentError(
            "Field '" + key +
            "' is an object in config but not a message in OfflineNodeEntities "
            "data");
      }
      if (field->is_repeated()) {
        // Repeated field found, we need to check all of them, but exit as long
        // as one matches.
        bool match_found = false;
        for (int i = 0; i < reflection->FieldSize(offline_node_entities, field);
             ++i) {
          ECCLESIA_ASSIGN_OR_RETURN(
              bool result, CheckOfflineNodeEntityInfoMatch(
                               value, reflection->GetRepeatedMessage(
                                          offline_node_entities, field, i)));
          if (result) {
            match_found = true;
            break;
          }
        }
        if (!match_found) {
          return false;
        }
        continue;
      }

      // Single field found, check if it matches.
      ECCLESIA_ASSIGN_OR_RETURN(
          bool result,
          CheckOfflineNodeEntityInfoMatch(
              value, reflection->GetMessage(offline_node_entities, field)));
      if (!result) {
        return false;
      }
      continue;
    }

    // If the value is a string, we need to check if the field is a string in
    // OfflineNodeEntities. If it is, then we need to check if the string
    // matches the regex string in the config.
    if (value.is_string()) {
      if (field->cpp_type() != FieldDescriptor::CPPTYPE_STRING) {
        return absl::InvalidArgumentError("Field '" + key +
                                          "' is a string in config but not a "
                                          "string in OfflineNodeEntities data");
      }
      std::string proto_value =
          reflection->GetString(offline_node_entities, field);
      std::string probe_value = value.get<std::string>();
      if (!EvaluateProbeRegexMatch(proto_value, probe_value)) {
        return false;
      }
    } else {
      return absl::InvalidArgumentError(
          "Unsupported OfflineNodeEntities Probe value type for field '" + key +
          "'");
    }
  }
  return true;
}

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

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

// Probes if the ipmi fru matches and updates the fru table and probed
// config map. Return true if probed successfully.
absl::StatusOr<bool> ProbeFru(
    nlohmann::json& ipmi_fru_object, const nlohmann::json& config,
    absl::string_view name, const FruTable& fru_table,
    ProbedConfigMap& probed_config_map,
    const OfflineNodeEntityInformation& offline_node_entities) {
  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* product_part_number =
        GetValueAsString(ipmi_fru, "PRODUCT_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 &&
        product_part_number == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: IpmiFru field is not a valid probe");
    }

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

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

      // Check if any of the FRU fields match the probe.
      bool board_product_name_matches_or_null =
          CheckProbeFieldMatch(board_product_name, fru, "BOARD_PRODUCT_NAME");
      bool product_product_name_matches_or_null = CheckProbeFieldMatch(
          product_product_name, fru, "PRODUCT_PRODUCT_NAME");
      bool part_number_matches_or_null =
          CheckProbeFieldMatch(part_number, fru, "BOARD_PART_NUMBER");
      bool product_part_number_matches_or_null =
          CheckProbeFieldMatch(product_part_number, fru, "PRODUCT_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 any 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 ||
          !product_part_number_matches_or_null ||
          !board_info_am2_matches_or_null || !board_info_am3_matches_or_null ||
          !board_info_am4_matches_or_null ||
          !product_info_am2_matches_or_null) {
        continue;
      }

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

      // If the key is in the format of "bus:address", we will parse the bus
      // and address and use them to construct the FruKey object. Otherwise,
      // default to the string representation of the FruKey.
      probed_data.fru_keys.push_back(FruKey(key));
      probed_data.config = config;
      LOG(INFO) << "Matched config: " << name << " with FRU: " << key;
    }
    if (is_fru_probed) {
      // As long as one IpmiFru field matches, we should break out of the loop,
      // we should not match the same FRU against the same config multiple
      // times.
      break;
    }
  }

  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,
    bool enable_deterministic_bmc,
    const OfflineNodeEntityInformation& offline_node_entities) {
  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, {{" ", "_"}});

    // Check for keyword based probes.
    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;
      }
    }

    // Perform json object based probes.
    nlohmann::json probe = *probe_result;
    // If probe is OfflineNodeEntityInfo, create a ready FRU object for this.
    auto offline_node_entity_info_it =
        probe.find(kOfflineNodeEntityInfoKeyword);
    if (offline_node_entity_info_it != probe.end()) {
      ECCLESIA_ASSIGN_OR_RETURN(
          bool offline_node_entity_info_match,
          CheckOfflineNodeEntityInfoMatch(
              offline_node_entity_info_it->get<nlohmann::json>(),
              offline_node_entities));

      if (!offline_node_entity_info_match) {
        continue;
      }
      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);
      fru_table.mutable_key_to_fru()->insert({name, entity_object});
      continue;
    }

    // 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,
                 offline_node_entities);
    if (!is_fru_probed.ok()) {
      return is_fru_probed.status();
    }

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

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

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

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

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

void SortChildrenResourceIds(TopologyConfig& topology_config) {
  for (auto& [_, node] : *topology_config.mutable_topology_config_nodes()) {
    std::sort(node.mutable_children_chassis_ids()->pointer_begin(),
              node.mutable_children_chassis_ids()->pointer_end(),
              [](const std::string* id_1, const std::string* id_2) {
                return *id_1 < *id_2;
              });
    std::sort(node.mutable_children_cable_ids()->pointer_begin(),
              node.mutable_children_cable_ids()->pointer_end(),
              [](const std::string* id_1, const std::string* id_2) {
                return *id_1 < *id_2;
              });
    std::sort(node.mutable_children_storage_ids()->pointer_begin(),
              node.mutable_children_storage_ids()->pointer_end(),
              [](const std::string* id_1, const std::string* id_2) {
                return *id_1 < *id_2;
              });
    std::sort(node.mutable_children_assembly_ids()->pointer_begin(),
              node.mutable_children_assembly_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>, 6>
    kSupportedHwmonTempSensorTypes = {{
        // go/keep-sorted start
        {"MAX31725", HWMON_TEMP_SENSOR_TYPE1_MAX31725},
        {"MAX31732", HWMON_TEMP_SENSOR_TYPE3_MAX31732},
        {"SA56004", HWMON_TEMP_SENSOR_TYPE4_SA56004},
        {"TMP431", HWMON_TEMP_SENSOR_TYPE6_TMP431},
        {"TMP461", HWMON_TEMP_SENSOR_TYPE5_TMP461},
        {"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},
        {"ADM1273", PSU_SENSOR_TYPE23_ADM1273},
        {"BMR490", PSU_SENSOR_TYPE17_BMR490},
        {"LTC2991", PSU_SENSOR_TYPE4_LTC2991},
        {"LTC4287", PSU_SENSOR_TYPE9_LTC4287},
        {"LX6301", PSU_SENSOR_TYPE14_LX6301},
        {"MAX20826", PSU_SENSOR_TYPE19_MAX20826},
        {"MAX34451", PSU_SENSOR_TYPE21_MAX34451},
        {"Q50SN12072", PSU_SENSOR_TYPE10_Q50SN12072},
        {"Q54SN120A4", PSU_SENSOR_TYPE11_Q54SN120A4},
        {"RAA228228", PSU_SENSOR_TYPE5_RAA228228},
        {"RAA229141", PSU_SENSOR_TYPE20_RAA229141},
        {"RAA229639", PSU_SENSOR_TYPE13_RAA229639},
        {"SBRMI_1_0", PSU_SENSOR_TYPE22_SBRMI_I3C},
        {"SBRMI_2_0", PSU_SENSOR_TYPE22_SBRMI_I3C},
        {"SBTSI_1_0", PSU_SENSOR_TYPE15_SBTSI_I3C},
        {"SBTSI_1_1", PSU_SENSOR_TYPE15_SBTSI_I3C},
        {"SBTSI_2_0", PSU_SENSOR_TYPE15_SBTSI_I3C},
        {"SBTSI_2_1", PSU_SENSOR_TYPE15_SBTSI_I3C},
        {"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},
        {"XDPE19284C", PSU_SENSOR_TYPE18_XDPE19284C},
        {"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();
      }
    }

    // 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.virtual_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());
    }
  }
}

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

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

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

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

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

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

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

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

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

bool EntityConfigJsonImpl::IsGpioSensor(std::string_view type) {
  return type == "GpioSensor";
}

bool EntityConfigJsonImpl::IsRedfishAggregatedSensor(std::string_view type) {
  return type == "RedfishAggregatedSensor";
}

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

bool EntityConfigJsonImpl::IsManager(std::string_view type) {
  return type == kManagerKeyword;
}

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_ptr = GetValueAsString(element, "Type");
  if (type_ptr == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a string");
  }
  std::string type = *type_ptr;
  // Replace all spaces with underscores in the type string.
  absl::StrReplaceAll({{" ", "_"}}, &type);

  // 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 (IsGpioSensor(type)) {
    tlbmc_supported = true;
    absl::StatusOr<GpioSensorConfig> gpio_sensor_config =
        ParseGpioSensorConfig(element, is_detected);
    if (!gpio_sensor_config.ok()) {
      return gpio_sensor_config.status();
    }
    gpio_sensor_config->mutable_entity_common_config()->set_board_config_key(
        config_name_with_index);
    data.gpio_sensor_configs.push_back(*gpio_sensor_config);
  }

  if (IsRedfishAggregatedSensor(type)) {
    tlbmc_supported = true;
    absl::StatusOr<RedfishAggregatedSensorConfig>
        redfish_aggregated_sensor_config =
            ParseRedfishAggregatedSensorConfig(element, is_detected);
    if (!redfish_aggregated_sensor_config.ok()) {
      return redfish_aggregated_sensor_config.status();
    }
    redfish_aggregated_sensor_config->mutable_entity_common_config()
        ->set_board_config_key(config_name_with_index);
    data.redfish_aggregated_sensor_configs.push_back(
        *redfish_aggregated_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) || IsManager(type) ||
      type == kComputerSystemKeyword) {
    tlbmc_supported = true;
  }

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

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

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

  return absl::OkStatus();
}

void EntityConfigJsonImpl::UpdateFruAndTopology(
    const RawFruTable& fru_table, const std::vector<RawFru>& raw_frus) {
  EntityConfigJsonImplData new_data = ReloadConfig(
      fru_table, enable_deterministic_bmc_ ? -1 : 0,
      enable_deterministic_bmc_
          ? ReloadType::kReloadAll  // reload all will not actually reload all
                                    // data but only mutable. See next
                                    // comment for details.
          : ReloadType::kReloadFruAndTopologyOnly);

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

  // TODO(b/469890768): we are supposed to update "immutable data" as well for
  // ondemand FRU rescan and update sensor collector with new data. Currently
  // the refresh will only refresh mutable data for FRU modeling, the exposed
  // sensor which in immutable data will not be updated, sensor collector will
  // not be reconfigured with new data.

  // 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) {
    for (const auto& raw_fru : raw_frus) {
      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()) {
    if (enable_deterministic_bmc_ && !raw_fru.present()) {
      // TODO(haoooamazing): Add logic to model absent but expected FRU instead
      // of skipping.
      continue;
    }

    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,
                     enable_deterministic_bmc_, offline_node_entities_);
  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};
    }

    const bool* compound_frus_ptr =
        GetValueAsBool(config_data.config, "CompoundFru");
    bool is_compound_fru = compound_frus_ptr != nullptr && *compound_frus_ptr;

    std::vector<std::vector<FruKey>> fru_groups;
    if (is_compound_fru) {
      if (!config_data.fru_keys.empty()) {
        absl::flat_hash_map<
            std::tuple<std::string, std::string, std::string, std::string>,
            std::vector<FruKey>>
            pn_sn_groups;
        for (const auto& fru_key : config_data.fru_keys) {
          const Fru& fru =
              mutable_data.fru_table.key_to_fru().at(fru_key.ToString());
          auto key =
              std::make_tuple(fru.data().fru_info().board_part_number(),
                              fru.data().fru_info().board_serial_number(),
                              fru.data().fru_info().product_part_number(),
                              fru.data().fru_info().product_serial_number());
          pn_sn_groups[key].push_back(fru_key);
        }
        for (auto const& [key, frus] : pn_sn_groups) {
          fru_groups.push_back(frus);
        }
      }
    } else {
      for (const auto& fru_key : config_data.fru_keys) {
        fru_groups.push_back({fru_key});
      }
    }

    // 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 < fru_groups.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);
      if (!fru_groups[i].empty() &&
          absl::StrContainsIgnoreCase(config_name_with_index, "$bus")) {
        absl::StrReplaceAll({{"_", " "}}, &config_name_with_index);
        absl::StatusOr<std::string> bus_value_substitute_result =
            EvaluateStrExpressionSubstitution(
                config_name_with_index,
                absl::StrContains(config_name_with_index, "$bus") ? "$bus"
                                                                  : "$BUS",
                absl::StrCat(fru_groups[i][0].bus));
        if (bus_value_substitute_result.ok()) {
          config_name_with_index = bus_value_substitute_result.value();
        }
        absl::StrReplaceAll({{" ", "_"}}, &config_name_with_index);
      }
      topology_config_node.set_name(config_name_with_index);
      for (size_t j = 0; j < fru_groups[i].size(); j++) {
        std::string fru_key = fru_groups[i][j].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) {
          const Fru& parent_fru =
              mutable_data.fru_table.key_to_fru().at(fru_key);
          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);
          *sub_fru_info.mutable_i2c_info() = parent_fru.i2c_info();
          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_power_port_config_status =
              ParsePowerPortConfig(element, topology_config_node);
          if (!parse_power_port_config_status.ok()) {
            mutable_data.parsed_status = parse_power_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};
          }

          absl::Status parse_manager_status =
              ParseManagerConfig(mutable_data, element, topology_config_node);
          if (!parse_manager_status.ok()) {
            mutable_data.parsed_status = parse_manager_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_system_status =
              ParseSystemConfig(mutable_data, element, topology_config_node);
          if (!parse_system_status.ok()) {
            mutable_data.parsed_status = parse_system_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};
        }

        absl::Status parse_power_supply_info_status =
            ParsePowerSupplyConfig(config_data.config, fru);
        if (!parse_power_supply_info_status.ok()) {
          mutable_data.parsed_status = parse_power_supply_info_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);

        if (is_subfru) {
          mutable_data.topology_config.mutable_fru_configs()->insert(
              {fru_key, config_name_with_index});
          topology_config_node.mutable_fru_info()->set_is_sub_fru(true);
          for (const auto& key_in_group : fru_groups[i]) {
            fru_key_to_sub_fru_config[key_in_group.ToString()].insert(
                config_name_with_index);
          }
        } else {
          for (const auto& key_in_group : fru_groups[i]) {
            mutable_data.topology_config.mutable_fru_configs()->insert(
                {key_in_group.ToString(), config_name_with_index});
          }
        }

        // tlBMC own cables by config.
        if ((!GetTlbmcConfig().fru_collector_module().own_cables_in_redfish() &&
             fru_info.attributes().resource_type() == RESOURCE_TYPE_CABLE)) {
          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);

    std::optional<uint64_t> index =
        GetValueAsUintFromStringOrInteger(threshold_element, "Index");
    if (!index.has_value()) {
      for (const auto& label : labels) {
        *label_to_threshold_configs[label].add_threshold_configs() =
            threshold_config;
      }
    } else {
      std::string label = absl::Substitute("temp$0", *index);
      if (std::find(labels.begin(), labels.end(), label) == labels.end()) {
        return absl::InvalidArgumentError(absl::StrCat(
            "Invalid threshold config: Index doesn't have matching Name",
            " config is ", threshold_element.dump()));
      }
      *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());

  absl::flat_hash_map<std::string, RelatedItem> name_to_related_item;
  ECCLESIA_ASSIGN_OR_RETURN(name_to_related_item, ParseRelatedItemMap(config));
  intel_cpu_sensor_config.mutable_name_to_related_item()->insert(
      name_to_related_item.begin(), name_to_related_item.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<GpioSensorConfig> EntityConfigJsonImpl::ParseGpioSensorConfig(
    const nlohmann::json& config, bool is_detected) {
  GpioSensorConfig gpio_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");
  }
  gpio_sensor_config.set_name(*name);

  const std::string* gpio_pin_name = GetValueAsString(config, "GpioPinName");
  if (gpio_pin_name == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: GpioPinName field is not a string or missing");
  }
  gpio_sensor_config.set_gpio_pin_name(*gpio_pin_name);

  ECCLESIA_RETURN_IF_ERROR(ParseCommonEntityConfig(config, gpio_sensor_config));

  constexpr int kDefaultMaxGpioReading = 1;
  constexpr int kDefaultMinGpioReading = 0;

  ReadingRangeConfigs reading_range_configs = ParseReadingRangeConfigs(
      config, kDefaultMinGpioReading, kDefaultMaxGpioReading);
  *gpio_sensor_config.mutable_reading_ranges() = reading_range_configs;

  gpio_sensor_config.set_unit(ParseSensorUnit(config));

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

  return gpio_sensor_config;
}

absl::StatusOr<RedfishAggregatedSensorConfig>
EntityConfigJsonImpl::ParseRedfishAggregatedSensorConfig(
    const nlohmann::json& config, bool is_detected) {
  RedfishAggregatedSensorConfig redfish_aggregated_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");
  }
  redfish_aggregated_sensor_config.set_name(*name);

  ECCLESIA_RETURN_IF_ERROR(
      ParseCommonEntityConfig(config, redfish_aggregated_sensor_config));

  const std::string* source = GetValueAsString(config, "Source");
  if (source == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Source field is not a string or missing");
  }
  redfish_aggregated_sensor_config.set_source(*source);

  const std::string* sensor_type = GetValueAsString(config, "ReadingType");
  if (sensor_type == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: ReadingType field is not a string or missing");
  }
  redfish_aggregated_sensor_config.set_sensor_type(*sensor_type);

  const std::string* sensor_units = GetValueAsString(config, "ReadingUnits");
  if (sensor_units == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: ReadingUnits field is not a string or missing");
  }
  redfish_aggregated_sensor_config.set_sensor_units(*sensor_units);

  const std::string* aggregation_prefix =
      GetValueAsString(config, "AggregationPrefix");
  if (aggregation_prefix == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: AggregationPrefix field is not a string or missing");
  }
  redfish_aggregated_sensor_config.set_aggregation_prefix(*aggregation_prefix);

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

  return redfish_aggregated_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::Status EntityConfigJsonImpl::ParseManagerConfig(
    EntityConfigJsonImplMutableData& mutable_data, const nlohmann::json& config,
    TopologyConfigNode& topology_config_node) {
  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 != kManagerKeyword) {
    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 manager "
                     "config: ",
                     config.dump()));
  }

  const nlohmann::json::array_t* manager_for_servers =
      GetValueAsArray(config, "ManagerForServers");
  if (manager_for_servers == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: ManagerForServers field is not found for manager "
        "config: ",
        config.dump()));
  }

  const std::string* manager_for_chassis =
      GetValueAsString(config, "ManagerForChassis");
  if (manager_for_chassis == nullptr) {
    return absl::InvalidArgumentError(absl::StrCat(
        "Invalid config: ManagerForChassis field is not found for manager "
        "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 manager "
        "config: ",
        config.dump()));
  }

  // Add manager to fru table.
  Fru manager;
  manager.mutable_attributes()->set_resource_type(RESOURCE_TYPE_MANAGER);
  manager.mutable_attributes()->set_key(*name);
  manager.mutable_attributes()->set_status(Status::STATUS_READY);
  manager.mutable_attributes()->mutable_refresh_policy()->set_refresh_mode(
      RefreshMode::REFRESH_MODE_ON_DEMAND);
  manager.mutable_data()->mutable_manager_info()->set_name(*name);
  manager.mutable_data()->mutable_manager_info()->set_manager_in_chassis(
      topology_config_node.name());
  for (const auto& manager_for_server : *manager_for_servers) {
    manager.mutable_data()->mutable_manager_info()->add_manager_for_servers(
        manager_for_server.get<std::string>());
  }
  manager.mutable_data()->mutable_manager_info()->set_manager_for_chassis(
      *manager_for_chassis);

  // Topologically this needs to be a child of the current chassis
  TopologyConfigNode manager_node;
  manager_node.set_name(*name);
  manager_node.mutable_fru_info()->set_fru_key(*name);
  manager_node.set_config_key(*name);
  // Assume manager is embedded in the chassis
  manager_node.mutable_location_context()->set_location_type(
      PART_LOCATION_TYPE_EMBEDDED);

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

  PortConfig manager_to_chassis_port_config;
  manager_to_chassis_port_config.set_port_type(PORT_TYPE_UPSTREAM);
  manager_to_chassis_port_config.set_port_name(*name);
  *manager_node.add_upstream_port_configs() =
      std::move(manager_to_chassis_port_config);

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

  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::ParseSystemConfig(
    EntityConfigJsonImplMutableData& mutable_data, const nlohmann::json& config,
    TopologyConfigNode& topology_config_node) {
  const bool* tlbmc_owned = GetValueAsBool(config, "TlbmcOwned");
  if (tlbmc_owned == nullptr || !*tlbmc_owned) {
    return absl::OkStatus();
  }

  const std::string* type_str = GetValueAsString(config, "Type");
  if (type_str == nullptr || *type_str != kComputerSystemKeyword) {
    return absl::OkStatus();
  }

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

  // Add system to fru table.
  Fru system_fru;
  system_fru.mutable_attributes()->set_resource_type(
      RESOURCE_TYPE_COMPUTER_SYSTEM);
  system_fru.mutable_attributes()->set_key(system_name);
  system_fru.mutable_attributes()->set_status(Status::STATUS_READY);
  system_fru.mutable_attributes()->mutable_refresh_policy()->set_refresh_mode(
      RefreshMode::REFRESH_MODE_ON_DEMAND);
  mutable_data.fru_table.mutable_key_to_fru()->insert(
      {system_name, std::move(system_fru)});

  TopologyConfigNode system_node;
  system_node.set_name(system_name);
  system_node.mutable_fru_info()->set_fru_key(system_name);
  system_node.set_config_key(system_name);

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

  PortConfig system_to_chassis_port_config;
  system_to_chassis_port_config.set_port_type(PORT_TYPE_UPSTREAM);
  system_to_chassis_port_config.set_port_name(system_name);
  *system_node.add_upstream_port_configs() =
      std::move(system_to_chassis_port_config);

  mutable_data.topology_config.mutable_topology_config_nodes()->insert(
      {system_name, std::move(system_node)});
  mutable_data.topology_config.mutable_fru_configs()->insert(
      {system_name, system_name});

  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()});
  } else if (downstream_fru.attributes().resource_type() ==
             RESOURCE_TYPE_COMPUTER_SYSTEM) {
    current_node.add_children_system_ids(downstream_node.name());
  }

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

  return absl::OkStatus();
}

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

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

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

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

  // Map of power port name to config key.
  absl::flat_hash_map<std::string, std::string>
      upstream_power_port_name_to_config_key;
  for (const auto& [config_key, topology_config_node] :
       topology_config.topology_config_nodes()) {
    for (const auto& upstream_power_port_config :
         topology_config_node.upstream_power_port_configs()) {
      if (!upstream_power_port_config.port_name().empty()) {
        upstream_power_port_name_to_config_key[upstream_power_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);
    }

    // Apply the power topology
    for (const auto& [power_port_name, power_port_config] :
         current_node->power_port_configs()) {
      auto find_downstream_power_node_key_it =
          upstream_power_port_name_to_config_key.find(power_port_name);
      if (find_downstream_power_node_key_it ==
          upstream_power_port_name_to_config_key.end()) {
        continue;
      }

      absl::string_view downstream_power_node_key =
          find_downstream_power_node_key_it->second;
      // Downstream power node is always present in the topology config so will
      // not check for presence.
      TopologyConfigNode& downstream_power_node =
          topology_config.mutable_topology_config_nodes()->at(
              downstream_power_node_key);

      if (power_port_config.port_type() == PORT_TYPE_POWER_DOWNSTREAM) {
        downstream_power_node.add_powered_by_ids(current_node->config_key());
        current_node->add_powers_ids(downstream_power_node_key);
      }
    }
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  json["RedfishAggregatedSensorConfigs"] = nlohmann::json::array();
  for (const auto& redfish_aggregated_sensor_config :
       data_store_.immutable_data.redfish_aggregated_sensor_configs) {
    json["RedfishAggregatedSensorConfigs"].push_back(
        ProtoToJson(redfish_aggregated_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,
    OfflineNodeEntityInformation&& offline_node_entities,
    const RawFruTable& fru_table, size_t ad_hoc_fru_count,
    bool enable_deterministic_bmc)
    : immutable_config_list_(std::move(config_list)),
      enable_deterministic_bmc_(enable_deterministic_bmc),
      offline_node_entities_(std::move(offline_node_entities)),
      data_store_(PackDataIntoStore(
          ReloadConfig(fru_table, ad_hoc_fru_count, ReloadType::kReloadAll),
          enable_deterministic_bmc_)) {}

absl::StatusOr<std::unique_ptr<EntityConfig>> EntityConfigJsonImpl::Create(
    std::vector<nlohmann::json>&& config_list,
    OfflineNodeEntityInformation&& offline_node_entities,
    const RawFruTable& fru_table, size_t ad_hoc_fru_count,
    bool enable_deterministic_bmc) {
  auto entity_config = absl::WrapUnique(new EntityConfigJsonImpl(
      std::move(config_list), std::move(offline_node_entities), fru_table,
      ad_hoc_fru_count, enable_deterministic_bmc));
  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;
}

absl::StatusOr<OfflineNodeEntityInformation>
EntityConfigJsonImpl::ParseOfflineNodeEntities(
    absl::string_view offline_node_entities_path) {
  if (offline_node_entities_path.empty()) {
    return absl::InvalidArgumentError("OfflineNodeEntities path is empty.");
  }

  return ReadOfflineNodeEntityInformation(offline_node_entities_path);
}

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, bool enable_deterministic_bmc) {
  return EntityConfigJsonImplDataStore{
      // TODO(b/469890768): immutable_data will be updated to
      // SimpleRcu<EntityConfigJsonImplImmutableData>(
      // std::move(data.immutable_data), enable_deterministic_bmc ? -1 : 0) for
      // store refresh in deterministic mode. Current the refresh will only
      // refresh mutable data for FRU modeling, the exposed sensor which in
      // immutable data will not be updated.
      .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
