#include "tlbmc/configs/entity_config_json_impl.h"

#include <stdint.h>

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <memory>
#include <optional>
#include <queue>
#include <string>
#include <string_view>
#include <unordered_map>
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/log.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/str_join.h"
#include "absl/strings/str_replace.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "g3/macros.h"
#include "time/proto.h"
#include "nlohmann/json_fwd.hpp"
#include "nlohmann/json.hpp"
#include "json_utils.h"
#include "tlbmc/central_config/config.h"
#include "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 "hwmon_temp_sensor_config.pb.h"
#include "i2c_common_config.pb.h"
#include "psu_sensor_config.pb.h"
#include "reading_range_config.pb.h"
#include "shared_mem_sensor_config.pb.h"
#include "threshold_config.pb.h"
#include "topology_config.pb.h"
#include "tlbmc/rcu/simple_rcu.h"
#include "fru.pb.h"
#include "resource.pb.h"
#include "sensor.pb.h"
#include "router_interface.h"
#include "re2/re2.h"

namespace milotic_tlbmc {

namespace {

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

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

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

constexpr absl::string_view kCableDownstreamConnectionKeyword =
    "CableDownstreamConnection";
constexpr absl::string_view kCableUpstreamConnectionKeyword =
    "CableUpstreamConnection";
constexpr absl::string_view kDownstreamPortKeyword = "PortDownstream";
constexpr absl::string_view kUpstreamConnectionKeyword = "UpstreamConnection";
constexpr const char* kProbeKeyword = "ProbeV2";

constexpr absl::string_view kChassisTypeKeyword = "ChassisType";
constexpr absl::string_view kStorageKeyword = "Storage";
constexpr absl::string_view kProcessorKeyword = "Processor";
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 std::array<std::pair<std::string_view, SensorUnit>, 6>
    kSupportedSensorUnits = {
        // go/keep-sorted start
        {
            {"DegreeCelsius", SensorUnit::UNIT_DEGREE_CELSIUS},
            {"Watt", SensorUnit::UNIT_WATT},
            {"Ampere", SensorUnit::UNIT_AMPERE},
            {"Volt", SensorUnit::UNIT_VOLT},
            {"RPM", SensorUnit::UNIT_REVOLUTION_PER_MINUTE},
            {"Percent", SensorUnit::UNIT_PERCENT},
        }
        // go/keep-sorted end
};

absl::Status ParseProcessorConfig(const nlohmann::json& config,
                                  TopologyConfigNode& topology_config_node) {
  const std::string* type_str = GetValueAsString(config, "Type");
  if (type_str == nullptr || *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");
  }

  topology_config_node.add_children_processor_ids(*processor_id);
  return absl::OkStatus();
}

absl::Status ParseStorageConfig(const nlohmann::json& config,
                                TopologyConfigNode& topology_config_node,
                                size_t index) {
  const nlohmann::json* storage_config =
      GetValueAsJson(config, kStorageKeyword);
  if (storage_config == nullptr) {
    return absl::OkStatus();
  }
  const std::string* storage_id = GetValueAsString(*storage_config, "Id");
  if (storage_id == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Id field is not found for storage config");
  }
  std::string storage_id_with_index = *storage_id;
  absl::StrReplaceAll({{"$index", absl::StrCat(index + 1)}},
                      &storage_id_with_index);
  topology_config_node.add_children_storage_ids(storage_id_with_index);

  return absl::OkStatus();
}

SensorUnit 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::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 &&
       *port_type_str != kCableDownstreamConnectionKeyword &&
       *port_type_str != kCableUpstreamConnectionKeyword)) {
    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);
  port_config.set_port_type(PORT_TYPE_DOWNSTREAM);
  if (*port_type_str == kUpstreamConnectionKeyword) {
    if (topology_config_node.has_upstream_port_config()) {
      return absl::InvalidArgumentError(
          "Invalid config: Multiple Upstream connection configs present");
    }
    *topology_config_node.mutable_upstream_port_config() =
        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);
    topology_config_node.mutable_port_configs()->insert(
        {*port_name, std::move(port_config)});
  } else if (*port_type_str == kCableUpstreamConnectionKeyword ||
             *port_type_str == kCableDownstreamConnectionKeyword) {
    const std::string* port_label = GetValueAsString(config, "CableId");
    if (port_label == nullptr) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Invalid config: CableId field is not found for cable ",
          (*port_type_str == kCableUpstreamConnectionKeyword) ? "upstream"
                                                              : "downstream",
          " connection"));
    }
    port_config.set_port_label(*port_label);
    if (*port_type_str == kCableUpstreamConnectionKeyword) {
      port_config.set_port_type(PORT_TYPE_CABLE_UPSTREAM);
      *topology_config_node.mutable_upstream_cable_port_config() =
          std::move(port_config);
    } else {
      port_config.set_port_type(PORT_TYPE_CABLE_DOWNSTREAM);
      topology_config_node.mutable_cable_port_configs()->insert(
          {*port_name, std::move(port_config)});
    }
  }
  return absl::OkStatus();
}

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

  return chassis_type;
}

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

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

  return resource_type;
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

bool IsSubFru(const nlohmann::json& probe) {
  const bool* is_sub_fru = GetValueAsBool(probe, "IsSubFru");
  if (is_sub_fru == nullptr) {
    return false;
  }
  return *is_sub_fru;
}

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

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

absl::StatusOr<ProbedConfigMap> ProcessConfigs(
    const std::vector<nlohmann::json>& config_list, FruTable& fru_table) {
  ProbedConfigMap probed_config_map;
  for (const auto& config : config_list) {
    absl::StatusOr<nlohmann::json> probe_result =
        GetObject(config, kProbeKeyword);
    if (!probe_result.ok()) {
      continue;
    }

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

    const std::string* true_str = probe_result->get_ptr<const std::string*>();
    bool true_value = true_str != nullptr && *true_str == "TRUE";
    // Check if the probe is a true value.
    if (true_value) {
      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);
      fru_table.mutable_key_to_fru()->insert({name, entity_object});
      continue;
    }
    bool skip_value = true_str != nullptr && *true_str == "FALSE";
    if (skip_value) {
      continue;
    }
    nlohmann::json probe = *probe_result;
    // Perform probe.
    // Match Fru if config contains IPMI FRU probe.
    auto ipmi_fru_it = probe.find("IpmiFru");
    if (ipmi_fru_it == probe.end()) {
      return absl::InvalidArgumentError(
          "Invalid config: IpmiFru field is not a valid probe");
    }
    auto ipmi_fru_object = ipmi_fru_it->get<nlohmann::json>();
    // Wrap single IpmiFru object in array to simplify logic below.
    if (!ipmi_fru_object.is_array()) {
      ipmi_fru_object = nlohmann::json::array({ipmi_fru_object});
    }
    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_info_am2 =
          GetValueAsString(ipmi_fru, "PRODUCT_INFO_AM2");
      if (board_product_name == nullptr && product_product_name == nullptr &&
          bus == nullptr && address == nullptr && part_number == nullptr &&
          product_info_am2 == nullptr) {
        return absl::InvalidArgumentError(
            "Invalid config: IpmiFru field is not a valid probe");
      }

      // Check if the FRU matches the probe.
      for (const auto& [key, fru] : fru_table.key_to_fru()) {
        bool i2c_info_matches_or_null = false;
        if ((bus == nullptr && address == nullptr) ||
            (bus != nullptr && *bus == fru.i2c_info().bus() &&
             address != nullptr && *address == fru.i2c_info().address())) {
          i2c_info_matches_or_null = true;
        }

        // 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_info_am2_matches_or_null =
            CheckProbeFieldMatch(product_info_am2, fru, "PRODUCT_INFO_AM2");

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

        // This condition will check that
        // 1. Only configs containing in $index can have multiple Fru probe true
        // 2. A Fru cannot match multiple probes within one config
        // 3. Multiple configs cannot probe true with the same name
        if (probed_config_map.contains(name) &&
            !absl::StrContains(name, "$index")) {
          return absl::InvalidArgumentError(absl::StrCat(
              "Invalid config: Frus match the same config multiple"
              " times but config name does not contain $index : ",
              name));
        }
        // If we reach here, the FRU matches the probe and is unique.
        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;
      }
      // Sort the found FRU keys for each config.
      if (auto probed_data_it = probed_config_map.find(name);
          probed_data_it != probed_config_map.end()) {
        std::sort(probed_data_it->second.fru_keys.begin(),
                  probed_data_it->second.fru_keys.end());
      }
    }
  }
  return probed_config_map;
}

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_processor_ids()->pointer_begin(),
              node.mutable_children_processor_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;
              });
  }
}

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

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

constexpr std::array<std::pair<std::string_view, PsuSensorType>, 8>
    kSupportedPsuSensorTypes = {
        // go/keep-sorted start
        {{"ADM1266", PSU_SENSOR_TYPE1_ADM1266},
         {"ADM1272", PSU_SENSOR_TYPE2_ADM1272},
         {"LTC2991", PSU_SENSOR_TYPE4_LTC2991},
         {"RAA228228", PSU_SENSOR_TYPE5_RAA228228},
         {"TDA38725", PSU_SENSOR_TYPE6_TDA38725},
         {"TDA38740", PSU_SENSOR_TYPE7_TDA38740},
         {"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
};

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

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

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

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

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

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

absl::Status EntityConfigJsonImpl::ParseAndPopulateConfig(
    EntityConfigJsonImplImmutableData& data, const nlohmann::json& element,
    absl::string_view config_name_with_index) {
  const bool* tlbmc_owned = GetValueAsBool(element, "TlbmcOwned");
  if (tlbmc_owned == nullptr || !*tlbmc_owned) {
    return absl::OkStatus();
  }
  const std::string* type = GetValueAsString(element, "Type");
  if (type == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a string");
  }
  // HWMon temperature sensor.
  HwmonTempSensorType hwmon_temp_sensor_type = IsHwmonTempSensor(*type);
  if (hwmon_temp_sensor_type != HWMON_TEMP_SENSOR_TYPE0_UNKNOWN) {
    absl::StatusOr<HwmonTempSensorConfig> hwmon_temp_sensor_config =
        ParseHwmonTempSensorConfig(hwmon_temp_sensor_type, element);
    if (!hwmon_temp_sensor_config.ok()) {
      return hwmon_temp_sensor_config.status();
    }
    *hwmon_temp_sensor_config->mutable_entity_common_config()
         ->mutable_board_config_name() = config_name_with_index;
    if (!hwmon_temp_sensor_config->entity_common_config().has_related_item()) {
      // By default, if no related item is specified, the sensor related item
      // will be its chassis
      RelatedItem default_related_chassis;
      default_related_chassis.set_id(
          hwmon_temp_sensor_config->entity_common_config().board_config_name());
      default_related_chassis.set_type(RESOURCE_TYPE_BOARD);
      *hwmon_temp_sensor_config->mutable_entity_common_config()
           ->mutable_related_item() = default_related_chassis;
    }
    data.hwmon_temp_sensor_configs.push_back(*hwmon_temp_sensor_config);
  }

  // PSU sensor.
  PsuSensorType psu_sensor_type = IsPsuSensor(*type);
  if (psu_sensor_type != PSU_SENSOR_TYPE0_UNKNOWN) {
    absl::StatusOr<PsuSensorConfig> psu_sensor_config =
        ParsePsuSensorConfig(psu_sensor_type, element);
    if (!psu_sensor_config.ok()) {
      return psu_sensor_config.status();
    }
    *psu_sensor_config->mutable_entity_common_config()
         ->mutable_board_config_name() = config_name_with_index;
    if (!psu_sensor_config->entity_common_config().has_related_item()) {
      // By default, if no related item is specified, the sensor related item
      // will be its chassis
      RelatedItem default_related_chassis;
      default_related_chassis.set_id(
          psu_sensor_config->entity_common_config().board_config_name());
      default_related_chassis.set_type(RESOURCE_TYPE_BOARD);
      *psu_sensor_config->mutable_entity_common_config()
           ->mutable_related_item() = default_related_chassis;
    }
    data.psu_sensor_configs.push_back(*psu_sensor_config);
  }

  // FAN controller
  FanControllerType fan_controller_type = IsFanController(*type);
  if (fan_controller_type != FAN_CONTROLLER_TYPE_UNKNOWN) {
    absl::StatusOr<FanControllerConfig> fan_controller_config =
        ParseFanControllerConfig(fan_controller_type, element);
    if (!fan_controller_config.ok()) {
      return fan_controller_config.status();
    }
    data.fan_controller_configs.push_back(*fan_controller_config);
  }

  FanPwmType fan_pwm_type = IsFanPwm(*type);
  if (fan_pwm_type != PWM_SENSOR_TYPE_UNKNOWN) {
    absl::StatusOr<FanPwmConfig> fan_pwm_config =
        ParseFanPwmConfig(fan_pwm_type, element);
    if (!fan_pwm_config.ok()) {
      return fan_pwm_config.status();
    }
    *fan_pwm_config->mutable_entity_common_config()
         ->mutable_board_config_name() = config_name_with_index;
    data.fan_pwm_configs.push_back(*fan_pwm_config);
  }

  FanTachType fan_tach_type = IsFanTach(*type);
  if (fan_tach_type != TACH_SENSOR_TYPE_UNKNOWN) {
    absl::StatusOr<FanTachConfig> fan_tach_config =
        ParseFanTachConfig(fan_tach_type, element);
    if (!fan_tach_config.ok()) {
      return fan_tach_config.status();
    }
    *fan_tach_config->mutable_entity_common_config()
         ->mutable_board_config_name() = config_name_with_index;
    data.fan_tach_configs.push_back(*fan_tach_config);
  }

  SharedMemSensorType shared_mem_sensor_type = IsSharedMemSensor(*type);
  if (shared_mem_sensor_type != SHARED_MEM_SENSOR_TYPE_TYPE0_UNKNOWN) {
    absl::StatusOr<SharedMemSensorConfig> shared_mem_sensor_config =
        ParseSharedMemSensorConfig(shared_mem_sensor_type, element);
    if (!shared_mem_sensor_config.ok()) {
      return shared_mem_sensor_config.status();
    }
    *shared_mem_sensor_config->mutable_entity_common_config()
         ->mutable_board_config_name() = config_name_with_index;
    data.shared_mem_sensor_configs.push_back(*shared_mem_sensor_config);
  }

  return absl::OkStatus();
}

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

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

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

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

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

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

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

  absl::StatusOr<ProbedConfigMap> probed_config_map =
      ProcessConfigs(immutable_config_list_, mutable_data.fru_table);
  if (!probed_config_map.ok()) {
    mutable_data.parsed_status = probed_config_map.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 (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] : *probed_config_map) {
    // Check if config belongs to a sub FRU.
    // We have already checked that the config has a probe in `ProcessConfigs`.
    bool is_subfru = IsSubFru(config_data.config.at(kProbeKeyword));

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

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

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

      // 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()->set_chassis_type(
            ParseChassisType(config_data.config));
      }

      ParsePartLocationType(config_data.config, topology_config_node);
      ParseRootChassisLocationCode(config_data.config, topology_config_node);
      if (is_subfru &&
          topology_config_node.location_context().location_type() !=
              PART_LOCATION_TYPE_EMBEDDED) {
        mutable_data.parsed_status = absl::InternalError(absl::StrCat(
            "Invalid config: Sub FRU ", topology_config_node.name(),
            " has part location type ",
            topology_config_node.location_context().location_type(),
            ". All sub FRUs should have part location type "
            "PART_LOCATION_TYPE_EMBEDDED."));
      }

      absl::StatusOr<nlohmann::json> exposes =
          GetObject(config_data.config, "Exposes");
      if (!exposes.ok()) {
        mutable_data.parsed_status = exposes.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 auto* elements = exposes->get_ptr<const nlohmann::json::array_t*>();
      if (elements == nullptr) {
        mutable_data.parsed_status = absl::InvalidArgumentError(absl::StrCat(
            "Invalid config: The JSON field `Exposes` is not an array", name));
        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")) {
          element["Bus"] = fru_info.i2c_info().bus();
        }

        // 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);
          if (!config_parse_status.ok()) {
            mutable_data.parsed_status = config_parse_status;
            return EntityConfigJsonImplData{
                .immutable_data = std::move(immutable_data),
                .mutable_data = std::move(mutable_data),
                .max_updates_to_mutable_data = ad_hoc_fru_count};
          }
        }

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

        absl::Status parse_processor_status =
            ParseProcessorConfig(element, topology_config_node);
        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_storage_status =
          ParseStorageConfig(config_data.config, topology_config_node, i);
      if (!parse_storage_status.ok()) {
        mutable_data.parsed_status = parse_storage_status;
        return EntityConfigJsonImplData{
            .immutable_data = std::move(immutable_data),
            .mutable_data = std::move(mutable_data),
            .max_updates_to_mutable_data = ad_hoc_fru_count};
      }

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

      topology_config_node.mutable_fru_info()->set_fru_key(fru_key);
      if (!is_subfru) {
        mutable_data.topology_config.mutable_fru_configs()->insert(
            {fru_key, config_name_with_index});
      } else {
        topology_config_node.mutable_fru_info()->set_is_sub_fru(true);
        fru_key_to_sub_fru_config[fru_key].insert(config_name_with_index);
      }

      if (fru_info.attributes().resource_type() == RESOURCE_TYPE_CABLE) {
        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.has_upstream_port_config() ||
          !topology_config_node.port_configs().empty() ||
          topology_config_node.has_upstream_cable_port_config() ||
          !topology_config_node.cable_port_configs().empty()) {
        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_names] : fru_key_to_sub_fru_config) {
    for (const auto& config_name : config_names) {
      auto it =
          mutable_data.topology_config.mutable_fru_configs()->find(fru_key);
      if (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_name));
        return EntityConfigJsonImplData{
            .immutable_data = std::move(immutable_data),
            .mutable_data = std::move(mutable_data),
            .max_updates_to_mutable_data = ad_hoc_fru_count};
      }
      std::string config_name_with_index = it->second;
      // 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_name_with_index);
      *topology_config_node.mutable_sub_fru_config_names()->Add() = config_name;
    }
  }

  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().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_names] :
       fru_key_to_sub_fru_config) {
    fru_keys_with_sub_frus.insert(sub_fru_config_names.begin(),
                                  sub_fru_config_names.end());
  }

  absl::Status create_associations_status =
      CreateAssociationsBetweenTopologyConfigNodes(
          mutable_data.topology_config, mutable_data.fru_table,
          std::move(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);

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

std::unordered_map<std::string, ReadingRangeConfigs>
EntityConfigJsonImpl::ParseReadingRangeConfigs(
    const nlohmann::json& config, absl::Span<const std::string> labels) {
  std::unordered_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::StatusOr<I2cCommonConfig> EntityConfigJsonImpl::ParseI2cCommonConfig(
    const nlohmann::json& config) {
  I2cCommonConfig i2c_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()));
  }
  i2c_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: ");
  }
  i2c_config.set_address(address_uint64);
  return i2c_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<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<std::unordered_map<std::string, ThresholdConfigs>>
EntityConfigJsonImpl::ParseThresholdConfigs(const nlohmann::json& config) {
  std::unordered_map<std::string, ThresholdConfigs> label_to_threshold_configs;
  if (!config.contains("Thresholds")) {
    return label_to_threshold_configs;
  }
  const nlohmann::json::array_t* threshold_configs =
      GetValueAsArray(config, "Thresholds");
  if (threshold_configs == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Thresholds field is not an array");
  }
  for (const auto& threshold_element : *threshold_configs) {
    const std::string* name = GetValueAsString(threshold_element, "Name");
    if (name == nullptr) {
      return absl::InvalidArgumentError(
          "Invalid config: Name field is not a string or missing");
    }
    ECCLESIA_ASSIGN_OR_RETURN(ThresholdType threshold_type,
                              ParseThresholdType(*name));

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

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

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

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

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

absl::StatusOr<std::unordered_map<std::string, std::string>>
EntityConfigJsonImpl::ParseLabelToName(const nlohmann::json& config,
                                       absl::Span<const std::string> labels,
                                       bool ignore_zero_index_name) {
  std::unordered_map<std::string, std::string> label_to_name;
  for (std::size_t i = 0; i < labels.size(); ++i) {
    const std::string& label = labels[i];
    std::string key = absl::Substitute("$0_Name", 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] = *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) {
  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_i2c_common_config(),
      ParseI2cCommonConfig(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;
    }
    std::unordered_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());

  return hwmon_temp_sensor_config;
}

absl::StatusOr<FanControllerConfig>
EntityConfigJsonImpl::ParseFanControllerConfig(FanControllerType type,
                                               const nlohmann::json& config) {
  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_i2c_common_config(),
                            ParseI2cCommonConfig(config));

  return fan_controller_config;
}

absl::StatusOr<PsuSensorConfig> EntityConfigJsonImpl::ParsePsuSensorConfig(
    PsuSensorType type, const nlohmann::json& config) {
  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_i2c_common_config(),
                            ParseI2cCommonConfig(config));
  ECCLESIA_RETURN_IF_ERROR(ParseCommonEntityConfig(config, psu_sensor_config));

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

  std::unordered_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());

  std::unordered_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());

  std::unordered_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());

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

  return psu_sensor_config;
}

absl::StatusOr<FanPwmConfig> EntityConfigJsonImpl::ParseFanPwmConfig(
    FanPwmType type, const nlohmann::json& config) {
  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_i2c_common_config(),
                            ParseI2cCommonConfig(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;
  }

  return fan_pwm_config;
}

absl::StatusOr<FanTachConfig> EntityConfigJsonImpl::ParseFanTachConfig(
    FanTachType type, const nlohmann::json& config) {
  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_i2c_common_config(),
                            ParseI2cCommonConfig(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));

  std::unordered_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;
  }

  return fan_tach_config;
}

absl::StatusOr<SharedMemSensorConfig>
EntityConfigJsonImpl::ParseSharedMemSensorConfig(SharedMemSensorType type,
                                                 const nlohmann::json& config) {
  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));

  std::unordered_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));

  return shared_mem_sensor_config;
}

absl::Status EntityConfigJsonImpl::CreateAssociationsBetweenTopologyConfigNodes(
    TopologyConfig& topology_config, FruTable& fru_table,
    absl::flat_hash_set<absl::string_view> expected_nodes_traversed) {
  // Find root node in TopologyConfig.
  std::string root_chassis_location_code;
  for (const auto& [config_name, 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.has_upstream_port_config() &&
        !topology_config_node.has_upstream_cable_port_config()) {
      if (topology_config.has_root_node_name()) {
        return absl::InternalError("Invalid config: Multiple root nodes found");
      }
      topology_config.set_root_node_name(config_name);
    }
  }

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

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

  // 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_name());
  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();

  std::queue<TopologyConfigNode*> node_queue;
  node_queue.push(&root_node);
  absl::flat_hash_set<absl::string_view> unexpected_nodes_traversed;
  while (!node_queue.empty()) {
    TopologyConfigNode* current_node = node_queue.front();
    node_queue.pop();
    if (expected_nodes_traversed.contains(current_node->name())) {
      expected_nodes_traversed.erase(current_node->name());
    } else {
      unexpected_nodes_traversed.insert(current_node->name());
    }
    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_name =
          upstream_port_name_to_config_name.find(port_name);
      if (find_downstream_node_name ==
          upstream_port_name_to_config_name.end()) {
        continue;
      }
      absl::string_view downstream_node_name =
          find_downstream_node_name->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_name);
      // If node is Sub-Fru then we add :device to the devpath and then append
      // the port label.
      if (downstream_node.fru_info().is_sub_fru()) {
        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()));
      }
      // 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());
      downstream_node.set_parent_resource_id(current_node->name());
      if (downstream_fru.attributes().resource_type() == RESOURCE_TYPE_BOARD) {
        current_node->add_children_chassis_ids(downstream_node.name());
      }
      node_queue.push(&downstream_node);
    }

    for (const auto& [port_name, port_config] :
         current_node->cable_port_configs()) {
      auto find_downstream_node_name =
          upstream_cable_port_name_to_config_name.find(port_name);
      if (find_downstream_node_name ==
          upstream_cable_port_name_to_config_name.end()) {
        continue;
      }
      absl::string_view downstream_node_name =
          find_downstream_node_name->second;
      TopologyConfigNode& downstream_node =
          topology_config.mutable_topology_config_nodes()->at(
              downstream_node_name);
      auto find_cable_fru =
          topology_config.mutable_topology_config_nodes()->find(
              port_config.port_label());
      if (find_cable_fru ==
          topology_config.mutable_topology_config_nodes()->end()) {
        return absl::InternalError(absl::StrCat(
            "Invalid config: Cable config name does not match cable connection "
            "CableId: ",
            port_config.port_label(), " cannot populate this cable."));
      }
      TopologyConfigNode& cable_topology_node = find_cable_fru->second;
      if (current_fru.attributes().resource_type() != RESOURCE_TYPE_CABLE) {
        downstream_node.mutable_location_context()->set_devpath(
            absl::StrCat(current_node->mutable_location_context()->devpath(),
                         "/", "DOWNLINK"));
        node_queue.push(&downstream_node);
        cable_topology_node.set_parent_resource_id(current_node->name());
        current_node->add_children_cable_ids(cable_topology_node.name());
      } else {
        downstream_node.add_children_cable_ids(cable_topology_node.name());
      }
    }
  }

  if (!expected_nodes_traversed.empty() ||
      !unexpected_nodes_traversed.empty()) {
    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(expected_nodes_traversed, ", "),
        absl::StrJoin(unexpected_nodes_traversed, ", ")));
  }
  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_name) const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  const auto fru_config_it =
      topology_config->topology_config_nodes().find(config_name);
  if (fru_config_it == topology_config->topology_config_nodes().end()) {
    return absl::NotFoundError(
        absl::StrCat("Config name not found: ", config_name));
  }
  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::GetAllConfigNames() const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  std::vector<std::string> config_names;
  for (const auto& [config_name, topology_config_node] :
       topology_config->topology_config_nodes()) {
    if (!topology_config_node.not_owned_by_tlbmc()) {
      config_names.push_back(config_name);
    }
  }
  return config_names;
}

absl::StatusOr<std::string> EntityConfigJsonImpl::GetConfigNameByFruKey(
    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::GetFruKeyByConfigName(
    absl::string_view config_name) const {
  ECCLESIA_ASSIGN_OR_RETURN(const TopologyConfig* topology_config,
                            GetTopologyConfig());
  auto fru_config_it =
      topology_config->topology_config_nodes().find(config_name);
  if (fru_config_it == topology_config->topology_config_nodes().end()) {
    return absl::NotFoundError(
        absl::StrCat("Config name not found: ", config_name));
  }
  return fru_config_it->second.fru_info().fru_key();
}

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

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

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

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

  return json;
}

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

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

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

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

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

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

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

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

}  // namespace milotic_tlbmc
