#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 kBmcNetKeyword = "BmcNet";
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();
}

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

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

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* board_info_am2 = GetValueAsString(ipmi_fru, "BOARD_INFO_AM2");
      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 && 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 board_info_am2_matches_or_null =
            CheckProbeFieldMatch(board_info_am2, fru, "BOARD_INFO_AM2");
        bool product_info_am2_matches_or_null =
            CheckProbeFieldMatch(product_info_am2, fru, "PRODUCT_INFO_AM2");

        // If the FRU doesn't match the probe, continue to the next FRU.
        if (!i2c_info_matches_or_null || !board_product_name_matches_or_null ||
            !product_product_name_matches_or_null ||
            !part_number_matches_or_null || !board_info_am2_matches_or_null ||
            !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;
              });
  }
}

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_name());
  default_related_board.set_type(RESOURCE_TYPE_BOARD);
  *entity_common_config.mutable_related_item() = default_related_board;
}

// 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_name, if an Assembly, we propagate the sensor config to the
// parent.
// Assigned board_config_name 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 PropagateSensorsFromAssemblyToBoard(
    EntityConfigJsonImplImmutableData& data,
    const TopologyConfig& topology_config, const FruTable& fru_table) {
  for (auto& config : data.hwmon_temp_sensor_configs) {
    TopologyConfigNode node = topology_config.topology_config_nodes().at(
        config.entity_common_config().board_config_name());
    const Fru& fru = fru_table.key_to_fru().at(node.fru_info().fru_key());
    if (fru.attributes().resource_type() == RESOURCE_TYPE_ASSEMBLY) {
      *config.mutable_entity_common_config()->mutable_board_config_name() =
          node.parent_resource_id();
    }
    if (!config.entity_common_config().has_related_item()) {
      SetDefaultRelatedItem(*config.mutable_entity_common_config());
    }
  }

  for (auto& config : data.psu_sensor_configs) {
    TopologyConfigNode node = topology_config.topology_config_nodes().at(
        config.entity_common_config().board_config_name());
    const Fru& fru = fru_table.key_to_fru().at(node.fru_info().fru_key());
    if (fru.attributes().resource_type() == RESOURCE_TYPE_ASSEMBLY) {
      *config.mutable_entity_common_config()->mutable_board_config_name() =
          node.parent_resource_id();
    }
    if (!config.entity_common_config().has_related_item()) {
      SetDefaultRelatedItem(*config.mutable_entity_common_config());
    }
  }

  for (auto& config : data.fan_pwm_configs) {
    TopologyConfigNode node = topology_config.topology_config_nodes().at(
        config.entity_common_config().board_config_name());
    const Fru& fru = fru_table.key_to_fru().at(node.fru_info().fru_key());
    if (fru.attributes().resource_type() == RESOURCE_TYPE_ASSEMBLY) {
      *config.mutable_entity_common_config()->mutable_board_config_name() =
          node.parent_resource_id();
    }
  }

  for (auto& config : data.fan_tach_configs) {
    TopologyConfigNode node = topology_config.topology_config_nodes().at(
        config.entity_common_config().board_config_name());
    const Fru& fru = fru_table.key_to_fru().at(node.fru_info().fru_key());
    if (fru.attributes().resource_type() == RESOURCE_TYPE_ASSEMBLY) {
      *config.mutable_entity_common_config()->mutable_board_config_name() =
          node.parent_resource_id();
    }
  }

  for (auto& config : data.shared_mem_sensor_configs) {
    TopologyConfigNode node = topology_config.topology_config_nodes().at(
        config.entity_common_config().board_config_name());
    const Fru& fru = fru_table.key_to_fru().at(node.fru_info().fru_key());
    if (fru.attributes().resource_type() == RESOURCE_TYPE_ASSEMBLY) {
      *config.mutable_entity_common_config()->mutable_board_config_name() =
          node.parent_resource_id();
    }
  }
}

}  // 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, bool is_subfru) {
  const bool* tlbmc_owned = GetValueAsBool(element, "TlbmcOwned");
  if (tlbmc_owned == nullptr || !*tlbmc_owned) {
    return absl::OkStatus();
  }
  bool tlbmc_supported = false;
  const std::string* type = GetValueAsString(element, "Type");
  if (type == nullptr) {
    return absl::InvalidArgumentError(
        "Invalid config: Type field is not a string");
  }
  // HWMon temperature sensor.
  HwmonTempSensorType hwmon_temp_sensor_type = IsHwmonTempSensor(*type);
  if (hwmon_temp_sensor_type != HWMON_TEMP_SENSOR_TYPE0_UNKNOWN) {
    tlbmc_supported = true;
    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;
    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) {
    tlbmc_supported = true;
    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;
    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) {
    tlbmc_supported = true;
    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) {
    tlbmc_supported = true;
    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) {
    tlbmc_supported = true;
    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) {
    tlbmc_supported = true;
    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);
  }

  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) {
  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.
    // RESOURCE_TYPE_ASSEMBLY indicates a config that is a sub FRU.
    absl::StatusOr<ResourceType> resource_type =
        ParseResourceType(config_data.config);

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

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

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

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

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

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

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

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

      absl::StatusOr<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, is_subfru);
          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};
        }

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

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

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

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

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

      if (fru_info.attributes().resource_type() == RESOURCE_TYPE_CABLE ||
          fru_info.attributes().resource_type() == RESOURCE_TYPE_ASSEMBLY) {
        topology_config_node.set_not_owned_by_tlbmc(true);
      }

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

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

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

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

    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.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()));
      }
      // 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());
      } else if (downstream_fru.attributes().resource_type() ==
                 RESOURCE_TYPE_ASSEMBLY) {
        current_node->add_children_assembly_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
