#include "tlbmc/collector/fru_collector.h"

#include <cctype>
#include <cstddef>
#include <cstdint>
#include <filesystem>  // NOLINT
#include <fstream>
#include <ios>
#include <memory>
#include <optional>
#include <string>
#include <system_error>  // NOLINT
#include <utility>
#include <vector>

#include "gbmc-hal/api/app/inventory/smbios_types.h"
#include "bus_topology.pb.h"
#include "absl/base/thread_annotations.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/functional/any_invocable.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "absl/time/time.h"
#include "g3/macros.h"
#include "nlohmann/json_fwd.hpp"
#include "json_utils.h"
#include "tlbmc/collector/resource_state_manager.h"
#include "ad_hoc_fru_config.pb.h"
#include "tlbmc/configs/entity_config.h"
#include "hal_common_config.pb.h"
#include "tlbmc/hal/fru_scanner.h"
#include "fru.pb.h"
#include "memory.pb.h"
#include "processor.pb.h"
#include "resource.pb.h"
#include "status.pb.h"
#include "tlbmc/scheduler/scheduler.h"
#include "tlbmc/time/time.h"
#include "tlbmc/utils/fram_utils.h"
#include "tlbmc/utils/fru_utils.h"
#include "google/protobuf/json/json.h"
#include "google/protobuf/util/json_util.h"

namespace milotic_tlbmc {

using AdHocFruScanContext = FruCollector::AdHocFruScanContext;

namespace {

// Extracts the entire trailing numeric digit sequence from the host ID (e.g.,
// "system12" -> "12", "system2" -> "2"). If the host ID represents a single
// system (e.g., "system") which does not contain a trailing digit suffix, it
// naturally returns an empty string "", forcing resolvers to fall back to
// single-system default file paths.
std::string ExtractHostNumber(absl::string_view host_id) {
  int i = static_cast<int>(host_id.size()) - 1;
  while (i >= 0 &&
         (std::isdigit(static_cast<unsigned char>(host_id[i])) != 0)) {
    --i;
  }
  return std::string(host_id.substr(i + 1));
}

}  // namespace

std::string FruCollector::GetFruKey(uint64_t fru_bus, uint64_t fru_address) {
  return absl::StrCat(fru_bus, ":", fru_address);
}

// These ad-hoc scanning configs will be in
// json["ProbeV2"]["AdHocFruConfig"]
std::vector<AdHocFruConfig> FruCollector::Options::ParseAdHocFruConfigs(
    const std::vector<nlohmann::json>& config_list) {
  std::vector<AdHocFruConfig> ad_hoc_fru_configs;
  for (const auto& config : config_list) {
    const nlohmann::json* tlbmc_config =
        GetValueAsJson(config, kTlbmcConfigKey);
    if (tlbmc_config == nullptr) {
      continue;
    }
    const nlohmann::json* ad_hoc_fru_scanning_config =
        GetValueAsJson(*tlbmc_config, kAdHocFruConfigKey);
    if (ad_hoc_fru_scanning_config == nullptr) {
      continue;
    }
    AdHocFruConfig ad_hoc_fru_config_proto;
    ::google::protobuf::json::ParseOptions opts;
    if (!::google::protobuf::json::JsonStringToMessage(ad_hoc_fru_scanning_config->dump(),
                                             &ad_hoc_fru_config_proto, opts)
             .ok()) {
      const std::string* config_name =
          milotic::authz::GetValueAsString(config, "Name");
      LOG(WARNING) << absl::StrCat(
          "Failed to convert ad-hoc FRU scanning config to proto for ",
          (config_name == nullptr ? "unnamed config"
                                  : std::string(*config_name)));
      continue;
    }
    ad_hoc_fru_configs.push_back(ad_hoc_fru_config_proto);
  }
  return ad_hoc_fru_configs;
}

nlohmann::json FruCollector::ToJson() const {
  nlohmann::json response;
  std::string json_string;
  ::google::protobuf::util::JsonPrintOptions opts;
  opts.preserve_proto_field_names = true;
  absl::MutexLock lock(fru_table_mutex_);
  if (!::google::protobuf::json::MessageToJsonString(fru_table_, &json_string, opts)
           .ok()) {
    LOG(ERROR) << "Failed to convert FRU table to JSON";
    return response;
  }
  return nlohmann::json::parse(json_string, nullptr, false);
}

// Returns the next scan info if there is a next scan period to schedule.
// Returns nullopt if there is no next scan period to schedule.
std::optional<AdHocFruScanContext> FruCollector::GetNextScanInfo(
    const AdHocFruConfig& ad_hoc_fru_config,
    const AdHocFruScanContext& scan_context) {
  if (ad_hoc_fru_config.periodic_scan_config_size() <=
      scan_context.cur_periodic_scan_config_index) {
    return std::nullopt;
  }

  // 0 indexed so if we are at the last scan period, we need to move onto next
  // period.
  if (ad_hoc_fru_config
          .periodic_scan_config(
              static_cast<int>(scan_context.cur_periodic_scan_config_index))
          .scan_count() ==
      scan_context.cur_periodic_scan_config_scan_count + 1) {
    // If we are at the last scan period, then no more scans.
    if (scan_context.cur_periodic_scan_config_index + 1 ==
        ad_hoc_fru_config.periodic_scan_config_size()) {
      return std::nullopt;
    }
    return AdHocFruScanContext{
        .cur_periodic_scan_config_index =
            scan_context.cur_periodic_scan_config_index + 1,
        .cur_periodic_scan_config_scan_count = 0,
        .found = scan_context.found};
  }

  return AdHocFruScanContext{
      .cur_periodic_scan_config_index =
          scan_context.cur_periodic_scan_config_index,
      .cur_periodic_scan_config_scan_count =
          scan_context.cur_periodic_scan_config_scan_count + 1,
      .found = scan_context.found};
}

void FruCollector::RescheduleAdHocFruScan(
    const AdHocFruConfig& ad_hoc_fru_config, size_t ad_hoc_fru_scan_context_id,
    const AdHocFruScanContext& scan_context) {
  // Schedule task with new period
  task_scheduler_->ScheduleOneShotAsync(
      [this, ad_hoc_fru_config,
       ad_hoc_fru_scan_context_id](absl::AnyInvocable<void()> on_done) {
        AttemptAdHocFruScan(ad_hoc_fru_config, ad_hoc_fru_scan_context_id);
        on_done();
      },
      DecodeGoogleApiProto(ad_hoc_fru_config
                               .periodic_scan_config(static_cast<int>(
                                   scan_context.cur_periodic_scan_config_index))
                               .scan_interval()));
}

void FruCollector::AttemptAdHocFruScan(const AdHocFruConfig& ad_hoc_fru_config,
                                       size_t ad_hoc_fru_scan_context_id) {
  AdHocFruScanContext scan_context =
      GetAdHocFruScanContext(ad_hoc_fru_scan_context_id);

  LOG(INFO) << "Attempting ad-hoc FRU scan for " << ad_hoc_fru_config.name();

  std::shared_ptr<EntityConfig> entity_config = GetEntityConfig();
  if (entity_config == nullptr) {
    LOG(WARNING) << "Entity config is not yet set. Will rescan later for "
                 << ad_hoc_fru_config.name();
    RescheduleAdHocFruScan(ad_hoc_fru_config, ad_hoc_fru_scan_context_id,
                           scan_context);
    return;
  }

  AdHocScannerType scanner_type = ad_hoc_fru_config.scanner_type();

  LOG(INFO) << "Ad-hoc config: " << ad_hoc_fru_config.name()
            << " requests scanner_type: "
            << AdHocScannerType_Name(scanner_type);
  auto it = options_.fru_scanners.find(scanner_type);
  if (it == options_.fru_scanners.end()) {
    LOG(ERROR) << "FruScanner not found for type "
               << AdHocScannerType_Name(scanner_type);
    return;
  }
  FruScanner* fru_scanner = it->second;
  if (fru_scanner == nullptr) {
    LOG(ERROR) << "FruScanner found for type "
               << AdHocScannerType_Name(scanner_type) << " but it is NULL";
    return;
  }

  // Lock the scan_in_progress_mutex_ to ensure that only one FRU scan is
  // in progress at a time.
  std::unique_ptr<absl::MutexLock> lock;
  if (options_.enable_deterministic_fru_scanning &&
      scanner_type == SCANNER_TYPE_DEFAULT_IPMI_I2C) {
    lock = std::make_unique<absl::MutexLock>(scan_in_progress_mutex_);
  }

  // If the FRU is already in the FRU table, then we can skip the scan to
  // avoid unnecessary I2C transactions and config reloading.
  std::string fru_key =
      GetFruKey(ad_hoc_fru_config.hal_common_config().bus(),
                ad_hoc_fru_config.hal_common_config().address());
  if (ContainsFru(fru_key)) {
    LOG(INFO)
        << "FRU already exists in the FRU table for ad-hoc FRU (presumbly "
           "found in periodic/deterministic FRU scanning): "
        << fru_key;
    scan_context.found = true;
    UpdateAdHocFruScanContext(ad_hoc_fru_scan_context_id, scan_context);
    return;
  }

  // Try to scan FRU
  absl::StatusOr<std::unique_ptr<I2cFruInfo>> ad_hoc_fru_info =
      fru_scanner->GetI2cFruInfoFromBus(
          static_cast<int>(ad_hoc_fru_config.hal_common_config().bus()),
          static_cast<int>(ad_hoc_fru_config.hal_common_config().address()),
          DecodeGoogleApiProto(ad_hoc_fru_config.delay_between_reads()));

  // If scan failed, next scan is already scheduled, so update scan
  // context and reschedule with different period if needed
  if (!ad_hoc_fru_info.ok()) {
    LOG(WARNING) << "Failed to scan ad-hoc FRU: " << ad_hoc_fru_config.name()
                 << " with status: " << ad_hoc_fru_info.status();
    ScanNextAdHocIfNeeded(ad_hoc_fru_config, ad_hoc_fru_scan_context_id,
                          scan_context);
    return;
  }
  LOG(INFO) << "Successfully scanned ad-hoc FRU: " << ad_hoc_fru_config.name();

  // If scan succeeded, update FRU table
  absl::StatusOr<RawFru> fru =
      CreateRawFruFromScanner(scanner_type, *ad_hoc_fru_info);
  if (!fru.ok()) {
    LOG(WARNING) << "Failed to create raw FRU from data: " << fru.status()
                 << " for FRU: " << ad_hoc_fru_config.name();
    ScanNextAdHocIfNeeded(ad_hoc_fru_config, ad_hoc_fru_scan_context_id,
                          scan_context);
    return;
  }
  AddFru(*fru);
  scan_context.found = true;
  UpdateAdHocFruScanContext(ad_hoc_fru_scan_context_id, scan_context);

  LOG(WARNING) << "Updated FRU table for FRU key: " << fru->key()
               << " for ad-hoc FRU: " << ad_hoc_fru_config.name();

  entity_config->UpdateFruAndTopology(GetCopyOfCurrentScannedFrus(),
                                      std::vector<RawFru>{*fru});
}

void FruCollector::ScanNextAdHocIfNeeded(
    const AdHocFruConfig& ad_hoc_fru_config, size_t ad_hoc_fru_scan_context_id,
    AdHocFruScanContext& scan_context) {
  std::optional<AdHocFruScanContext> next_scan_info =
      GetNextScanInfo(ad_hoc_fru_config, scan_context);

  // If there is no next scan info, then we are done with scanning.
  if (!next_scan_info.has_value()) {
    return;
  }

  // Sanity check periodic scan config size, fail safe.
  if (ad_hoc_fru_config.periodic_scan_config_size() <
      next_scan_info->cur_periodic_scan_config_index) {
    LOG(ERROR) << "Error in ad-hoc FRU scanning logic. No longer scanning "
               << ad_hoc_fru_config.name();
    return;
  }
  scan_context.cur_periodic_scan_config_index =
      next_scan_info->cur_periodic_scan_config_index;
  scan_context.cur_periodic_scan_config_scan_count =
      next_scan_info->cur_periodic_scan_config_scan_count;
  UpdateAdHocFruScanContext(ad_hoc_fru_scan_context_id, scan_context);
  RescheduleAdHocFruScan(ad_hoc_fru_config, ad_hoc_fru_scan_context_id,
                         scan_context);
  LOG(INFO) << "Rescheduled ad-hoc FRU scan for " << ad_hoc_fru_config.name();
}

void FruCollector::ScheduleAdHocFruScan(
    const AdHocFruConfig& ad_hoc_fru_config) {
  // Index to add to ad_hoc_fru_scan_contexts_
  size_t ad_hoc_fru_scan_context_id = GetAdHocFruScanContextsSize();
  AddAdHocFruScanContext(
      AdHocFruScanContext{.cur_periodic_scan_config_index = 0,
                          .cur_periodic_scan_config_scan_count = 0,
                          .found = false});

  // Scheduler automatically reruns task at defined periods
  task_scheduler_->ScheduleOneShotAsync(
      [this, ad_hoc_fru_config,
       ad_hoc_fru_scan_context_id](absl::AnyInvocable<void()> on_done) {
        AttemptAdHocFruScan(ad_hoc_fru_config, ad_hoc_fru_scan_context_id);
        on_done();
      },
      DecodeGoogleApiProto(
          ad_hoc_fru_config.periodic_scan_config(0).scan_interval()));
}

absl::StatusOr<const std::vector<std::string>&>
FruCollector::GetAssociatedSmbiosInventoryParts(
    const std::string& host_id) const {
  auto it = host_to_smbios_inventory_parts_.find(host_id);
  if (it == host_to_smbios_inventory_parts_.end()) {
    return absl::NotFoundError(absl::StrCat("Host ", host_id,
                                            " not found in host to SMBIOS "
                                            "inventory parts map."));
  }
  return it->second;
}

RawFru CreateAndPopulatePresentRawFru(
    const std::unique_ptr<I2cFruInfo>& i2c_fru_info,
    const absl::flat_hash_map<std::string, std::string>& fru_data_fields) {
  RawFru raw_fru;
  // Assuming we can have only one FRU per I2C bus/address pair
  raw_fru.set_key(
      FruCollector::GetFruKey(i2c_fru_info->bus, i2c_fru_info->address));

  // Populate I2C info.
  raw_fru.mutable_i2c_info()->set_bus(i2c_fru_info->bus);
  raw_fru.mutable_i2c_info()->set_address(i2c_fru_info->address);

  // Populate deterministic FRU scanning fields.
  raw_fru.set_present(true);
  raw_fru.set_expected_barepath(i2c_fru_info->expected_barepath);
  raw_fru.set_expected_part_number(i2c_fru_info->expected_part_number);
  raw_fru.set_expected_serial_number(i2c_fru_info->expected_serial_number);

  // Populate FRU data.
  FruData* fru_data = raw_fru.mutable_data();
  for (const auto& fru_data_field : fru_data_fields) {
    absl::string_view fru_data_field_stripped =
        absl::StripAsciiWhitespace(fru_data_field.second);
    (*fru_data->mutable_fields())[fru_data_field.first] =
        fru_data_field_stripped;
    if (fru_data_field.first == "BOARD_MANUFACTURER") {
      fru_data->mutable_fru_info()->set_board_manufacturer(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "BOARD_PRODUCT_NAME") {
      fru_data->mutable_fru_info()->set_board_product_name(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "BOARD_SERIAL_NUMBER") {
      fru_data->mutable_fru_info()->set_board_serial_number(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "BOARD_PART_NUMBER") {
      fru_data->mutable_fru_info()->set_board_part_number(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "PRODUCT_MANUFACTURER") {
      fru_data->mutable_fru_info()->set_product_manufacturer(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "PRODUCT_PRODUCT_NAME") {
      fru_data->mutable_fru_info()->set_product_product_name(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "PRODUCT_SERIAL_NUMBER") {
      fru_data->mutable_fru_info()->set_product_serial_number(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "PRODUCT_PART_NUMBER") {
      fru_data->mutable_fru_info()->set_product_part_number(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "PRODUCT_VERSION") {
      fru_data->mutable_fru_info()->set_product_version(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "PRODUCT_ASSET_TAG") {
      fru_data->mutable_fru_info()->set_product_asset_tag(
          fru_data_field_stripped);
    } else if (fru_data_field.first == "INTERNAL_MAC_ADDRESS") {
      fru_data->mutable_fru_info()->set_mac_address(fru_data_field_stripped);
    }
  }
  return raw_fru;
}

absl::StatusOr<RawFru> FruCollector::CreateRawFruFromScanner(
    AdHocScannerType scanner_type,
    const std::unique_ptr<I2cFruInfo>& i2c_fru_info) {
  switch (scanner_type) {
    case SCANNER_TYPE_DEFAULT_IPMI_I2C:
      return CreateRawFruFromIpmiFruData(i2c_fru_info);
    case SCANNER_TYPE_CAVIUM_HSM_FRAM:
      return CreateRawFruFromFramData(i2c_fru_info);
    default:
      LOG(ERROR) << "Unexpected value for AdHocScannerType: "
                 << static_cast<int>(scanner_type);
      return absl::InvalidArgumentError(
          absl::StrCat("Unexpected scanner type: ", scanner_type));
  }
}

absl::StatusOr<RawFru> FruCollector::CreateRawFruFromIpmiFruData(
    const std::unique_ptr<I2cFruInfo>& i2c_fru) {
  absl::flat_hash_map<std::string, std::string> fru_data_fields;

  // Get Fru data fields.
  size_t unknown_bus_object_count = 0;

  std::optional<std::string> product_name =
      getProductName(i2c_fru->data, fru_data_fields, i2c_fru->bus,
                     i2c_fru->address, unknown_bus_object_count);

  if (!product_name.has_value()) {
    return absl::InternalError(absl::StrCat(
        "Failed to get product name for FRU at bus: ", i2c_fru->bus,
        " address: ", i2c_fru->address));
  }

  return CreateAndPopulatePresentRawFru(i2c_fru, fru_data_fields);
}

std::optional<RawFruTable> FruCollector::DetectsAndReadsCachedFru(
    const std::string& cached_fru_table_path) {
  std::ifstream file(cached_fru_table_path, std::ios::binary);
  RawFruTable fru_table;
  if (!fru_table.ParseFromIstream(&file)) {
    LOG(WARNING) << "Error parsing cached FRU table file at path: "
                 << cached_fru_table_path;
    LOG(WARNING) << "Check the file exists and is in the correct format. Treat "
                    "this as no cached FRU table";
    return std::nullopt;
  }
  LOG(WARNING) << "Successfully read cached FRU table from file at path: "
               << cached_fru_table_path;
  return fru_table;
}

void FruCollector::WriteCachedFru(const RawFruTable& fru_table,
                                  const std::string& cached_fru_table_path) {
  std::filesystem::path path(cached_fru_table_path);
  std::filesystem::path parent_path = path.parent_path();
  std::error_code ec;
  bool exists_result = std::filesystem::exists(parent_path, ec);
  if (ec) {
    LOG(ERROR) << "Error checking exists for path '" << parent_path
               << "': " << ec.message();
    return;
  }
  if (!exists_result) {
    std::filesystem::create_directories(parent_path, ec);
    if (ec) {
      LOG(WARNING) << "Error creating directories for cached FRU table file at "
                      "path: "
                   << parent_path;
      return;
    }
  }

  std::ofstream file(cached_fru_table_path, std::ios::binary);
  if (!fru_table.SerializeToOstream(&file)) {
    LOG(WARNING) << "Error serializing cached FRU table to file at path: "
                 << cached_fru_table_path;
    return;
  }
  LOG(WARNING) << "Successfully wrote cached FRU table to file at path: "
               << cached_fru_table_path;
}

absl::StatusOr<std::unique_ptr<FruCollector>> FruCollector::Create(
    Options options) {
  if (options.fru_scanners.empty()) {
    return absl::InvalidArgumentError("FruScanners is empty");
  }

  // Validate AdHocFruConfigs against available scanners
  for (const auto& ad_hoc_config : options.ad_hoc_fru_scanning_configs) {
    AdHocScannerType scanner_type = ad_hoc_config.scanner_type();
    if (!options.fru_scanners.contains(scanner_type)) {
      return absl::InvalidArgumentError(
          absl::StrCat("Scanner type ", AdHocScannerType_Name(scanner_type),
                       " required by ad-hoc config '", ad_hoc_config.name(),
                       "' not found in provided fru_scanners map."));
    }
  }

  // Initialize the resource state manager.
  absl::flat_hash_map<RelatedState, std::vector<RelatedStateConfig>>
      state_to_configs;
  absl::flat_hash_map<std::string, RelatedState> fru_barepath_to_related_state;
  for (const auto& host_power_related_state_config :
       options.host_power_related_state_configs) {
    if (host_power_related_state_config.related_state() ==
        milotic_tlbmc::RELATED_STATE_NONE) {
      // Skip the resource state manager initialization if the related state is
      // NONE.
      LOG(WARNING) << "Illegal host power related state configuration: Related "
                      "state is NONE: "
                   << host_power_related_state_config;
      continue;
    }
    if (host_power_related_state_config.resource_identifiers().empty()) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Resource identifiers is empty for host power related state config: ",
          host_power_related_state_config));
    }
    if (host_power_related_state_config.host_id().empty()) {
      return absl::InvalidArgumentError(
          absl::StrCat("Host id is empty for host power related state config: ",
                       host_power_related_state_config));
    }

    state_to_configs[host_power_related_state_config.related_state()].push_back(
        host_power_related_state_config);
    // Store the FRU barepath for each related state for quick lookup later.
    for (const std::string& resource_identifier :
         host_power_related_state_config.resource_identifiers()) {
      if (resource_identifier.empty()) {
        return absl::InvalidArgumentError(
            absl::StrCat("Resource identifier is empty for host power related "
                         "state config: ",
                         host_power_related_state_config));
      }
      fru_barepath_to_related_state[resource_identifier] =
          host_power_related_state_config.related_state();
    }
  }

  options.fru_barepath_to_related_state =
      std::move(fru_barepath_to_related_state);

  absl::flat_hash_map<RelatedState, std::unique_ptr<ResourceStateManager>>
      resource_state_managers;
  for (const auto& [state, configs] : state_to_configs) {
    ECCLESIA_ASSIGN_OR_RETURN(
        resource_state_managers[state],
        ResourceStateManager::Create(
            {.target_state = state, .related_state_configs = configs}));
  }

  // Initialize the host to smbios inventory parts map.
  absl::flat_hash_map<std::string, std::vector<std::string>>
      host_to_smbios_inventory_parts;
  for (const auto& os_state_related_state_config :
       options.os_state_related_state_configs) {
    if (os_state_related_state_config.related_state() ==
        milotic_tlbmc::RELATED_STATE_NONE) {
      // Skip the host to smbios inventory parts initialization if the related
      // state is NONE.
      LOG(WARNING) << "Illegal host OS state related state configuration: "
                      "Related state is NONE: "
                   << os_state_related_state_config;
      continue;
    }
    if (os_state_related_state_config.resource_identifiers().empty()) {
      return absl::InvalidArgumentError(absl::StrCat(
          "Resource identifiers is empty for os state related state config: ",
          os_state_related_state_config));
    }
    if (os_state_related_state_config.host_id().empty()) {
      return absl::InvalidArgumentError(
          absl::StrCat("Host id is empty for os state related state config: ",
                       os_state_related_state_config));
    }
    for (const std::string& resource_identifier :
         os_state_related_state_config.resource_identifiers()) {
      if (resource_identifier.empty()) {
        return absl::InvalidArgumentError(
            absl::StrCat("Resource identifier is empty for os state related "
                         "state config: ",
                         os_state_related_state_config));
      }
      host_to_smbios_inventory_parts[os_state_related_state_config.host_id()]
          .push_back(resource_identifier);
    }
  }
  options.host_to_smbios_inventory_parts =
      std::move(host_to_smbios_inventory_parts);

  std::optional<RawFruTable> cached_fru_table =
      DetectsAndReadsCachedFru(options.cached_fru_table_path);
  // If cached FRU table is present, use it, and will not scan any fixed FRUs,
  // nor write cached FRU to file.
  if (cached_fru_table.has_value()) {
    return std::unique_ptr<FruCollector>(new FruCollector(
        std::move(options), std::move(*cached_fru_table),
        std::make_shared<TaskScheduler>(), std::move(resource_state_managers)));
  }

  RawFruTable fru_table;
  for (const auto& [scanner_type, scanner] : options.fru_scanners) {
    if (scanner == nullptr) {
      return absl::InvalidArgumentError(
          absl::StrCat("Scanner for type ", AdHocScannerType_Name(scanner_type),
                       " is null."));
    }
    LOG(INFO) << "Scanning FRUs with scanner type: "
              << AdHocScannerType_Name(scanner_type);

    if (scanner_type == SCANNER_TYPE_GPIO || scanner_type == SCANNER_TYPE_USB) {
      // Skip I2C scanning for GPIO FRUs.
      continue;
    }

    ECCLESIA_ASSIGN_OR_RETURN(std::vector<std::unique_ptr<I2cFruInfo>> frus,
                              scanner->ScanAllI2cFrus());

    for (const auto& fru_info : frus) {
      if (options.enable_deterministic_fru_scanning) {
        // Support I2C IPMI scanning for now. HSM FRAM to be supported later.
        if (scanner_type == SCANNER_TYPE_DEFAULT_IPMI_I2C) {
          // create RawFru for absent FRUs.
          if (!fru_info->present) {
            RawFru raw_fru;

            raw_fru.set_present(fru_info->present);
            if (fru_info->parsing_error) {
              raw_fru.set_parsing_error(true);
            }
            raw_fru.set_expected_barepath(fru_info->expected_barepath);
            raw_fru.set_expected_part_number(fru_info->expected_part_number);
            raw_fru.set_expected_serial_number(
                fru_info->expected_serial_number);

            raw_fru.set_key(GetFruKey(fru_info->bus, fru_info->address));
            raw_fru.mutable_i2c_info()->set_bus(fru_info->bus);
            raw_fru.mutable_i2c_info()->set_address(fru_info->address);
            LOG(WARNING) << "Updated FRU table for FRU key [FRU Absent]: "
                         << raw_fru.key() << " from scanner "
                         << AdHocScannerType_Name(scanner_type)
                         << ". Barepath: " << raw_fru.expected_barepath();
            fru_table.mutable_key_to_raw_fru()->insert(
                {raw_fru.key(), raw_fru});
            continue;
          }
        }
      }

      // Create RawFru from eeprom data for present FRUs. Not necessarily
      // means the FRU is valid (i.e., could be illogical).
      ECCLESIA_ASSIGN_OR_RETURN(
          RawFru fru, CreateRawFruFromScanner(scanner_type, fru_info));
      fru_table.mutable_key_to_raw_fru()->insert({fru.key(), fru});
      LOG(WARNING) << "Updated FRU table for FRU key [FRU Detected]: "
                   << fru.key() << " from scanner "
                   << AdHocScannerType_Name(scanner_type) << ". Barepath: "
                   << (fru.has_expected_barepath()
                           ? std::string(fru.expected_barepath())
                           : "N/A");
    }
  }

  WriteCachedFru(fru_table, options.cached_fru_table_path);

  return std::unique_ptr<FruCollector>(new FruCollector(
      std::move(options), std::move(fru_table),
      std::make_shared<TaskScheduler>(), std::move(resource_state_managers)));
}

absl::StatusOr<std::pair<std::string, std::string>>
FruCollector::GetPartAndSerialNumberFromFields(
    const absl::flat_hash_map<std::string, std::string>& fru_data_fields) {
  auto board_part_number_iter = fru_data_fields.find("BOARD_PART_NUMBER");
  auto board_serial_number_iter = fru_data_fields.find("BOARD_SERIAL_NUMBER");
  if (board_part_number_iter != fru_data_fields.end() &&
      !board_part_number_iter->second.empty() &&
      board_serial_number_iter != fru_data_fields.end() &&
      !board_serial_number_iter->second.empty()) {
    return std::make_pair(board_part_number_iter->second,
                          board_serial_number_iter->second);
  }

  LOG(WARNING) << "Failed to get board part number and serial number from FRU "
                  "data fields: at least one of them is missing. Trying to get "
                  "product part number and serial number instead.";

  auto product_part_number_iter = fru_data_fields.find("PRODUCT_PART_NUMBER");
  auto product_serial_number_iter =
      fru_data_fields.find("PRODUCT_SERIAL_NUMBER");
  if (product_part_number_iter != fru_data_fields.end() &&
      !product_part_number_iter->second.empty() &&
      product_serial_number_iter != fru_data_fields.end() &&
      !product_serial_number_iter->second.empty()) {
    return std::make_pair(product_part_number_iter->second,
                          product_serial_number_iter->second);
  }

  return absl::InternalError(absl::StrCat(
      "Failed to get part number and serial number from FRU data "
      "fields: ",
      absl::StrJoin(fru_data_fields, ",", absl::PairFormatter("="))));
}

absl::StatusOr<bool> FruCollector::IsFruMissingOk(
    const std::string& fru_barepath) {
  if (fru_barepath.empty()) {
    return absl::InvalidArgumentError("Fru barepath is empty.");
  }

  if (!fru_barepath_to_related_state_.contains(fru_barepath)) {
    // If the FRU is not in the map, it means that the FRU is not configured
    // with a related state, so it is not a related resource. Therefore, it is
    // not ok for it to be missing.
    DLOG(WARNING) << "Fru barepath: " << fru_barepath
                  << " is not found in fru_barepath_to_related_state_ map. "
                  << "Therefore, it is not ok for it to be missing.";
    return false;
  }

  RelatedState related_state = fru_barepath_to_related_state_[fru_barepath];
  if (!resource_state_managers_.contains(related_state)) {
    // If the resource state manager is not found, it means that the resource
    // state manager is not initialized or the FRU is in
    // fru_barepath_to_related_state_ map but not in the resource state manager.
    // Any of those cases should not happen in normal operation and should be
    // considered an internal error.
    return absl::InternalError(
        absl::StrCat("Resource state manager is not found for related state: ",
                     RelatedState_Name(related_state)));
  }

  return resource_state_managers_[related_state]
      ->IsStateRelatedResourceMissingOk(fru_barepath);
}

absl::StatusOr<FruTable> FruCollector::ScanAllFrusDeterministically() {
  DLOG(INFO) << "Entering ScanAllFrusDeterministically";
  if (!options_.enable_deterministic_fru_scanning) {
    return absl::FailedPreconditionError(
        "Deterministic FRU scanning is disabled. Cannot scan FRUs "
        "deterministically.");
  }

  // In the long term, we are supposed to support all types of FRUs, including
  // both I2C IPMI and FRAM based protocols with a all-in-one deterministic
  // scanner. In the short term, we will only support I2C IPMI with
  // SCANNER_TYPE_DEFAULT_IPMI_I2C.
  if (!options_.fru_scanners.contains(SCANNER_TYPE_DEFAULT_IPMI_I2C)) {
    return absl::InvalidArgumentError(
        "SCANNER_TYPE_DEFAULT_IPMI_I2C is required for deterministic FRU "
        "scanning.");
  }

  // Lock the scan_in_progress_mutex_ to ensure that only one FRU scan is
  // in progress at a time.
  absl::MutexLock lock(scan_in_progress_mutex_);
  FruTable fru_table;

  DLOG(INFO)
      << "Deterministic BMC: Scanning FRUs with deterministic FRU scanners. "
         "Number of deterministic FRU scanners: "
      << options_.deterministic_fru_scanners.size();
  // Scan all FRUs with the deterministic FRU scanners.
  for (const auto& [probe_path, scanner] :
       options_.deterministic_fru_scanners) {
    DLOG(INFO) << "Deterministic BMC: Scanning FRUs with deterministic FRU "
                  "scanner for probe path: "
               << uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::
                      ProbePath_Name(probe_path);
    switch (probe_path) {
      case uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::
          PROBE_PATH_NCSI: {
        ECCLESIA_ASSIGN_OR_RETURN(
            std::vector<std::unique_ptr<CableFruInfo>> frus,
            scanner->ScanAllCableFrus());
        for (const auto& fru_info : frus) {
          Fru fru;
          Attributes* attributes = fru.mutable_attributes();
          attributes->mutable_expected_hardware_info()->set_expected_barepath(
              fru_info->expected_barepath);
          if (fru_info->present) {
            attributes->set_presence_status(
                PresenceStatus::PRESENCE_STATUS_PRESENT);
          } else {
            attributes->set_presence_status(
                PresenceStatus::PRESENCE_STATUS_NOT_FOUND);
          }
          fru_table.mutable_key_to_fru()->insert(
              {fru_info->expected_barepath, fru});
        }
        break;
      }
      case uhmm::BmcMonitoredComponentsResponse::MonitoredComponent::
          PROBE_PATH_ADC: {
        ECCLESIA_ASSIGN_OR_RETURN(std::vector<std::unique_ptr<AdcFruInfo>> frus,
                                  scanner->ScanAllAdcFrus());
        for (const auto& fru_info : frus) {
          Fru fru;
          Attributes* attributes = fru.mutable_attributes();
          attributes->mutable_expected_hardware_info()->set_expected_barepath(
              fru_info->expected_barepath);
          attributes->set_presence_status(fru_info->presence_status);
          fru_table.mutable_key_to_fru()->insert(
              {fru_info->expected_barepath, fru});
        }
        break;
      }
      default:
        LOG(WARNING) << "Unsupported probe path: " << probe_path;
    }
  }

  // Scan all I2C Sensor Assembly FRUs with the default IPMI I2C scanner.
  auto& fru_scanner_ipmi_i2c =
      options_.fru_scanners[SCANNER_TYPE_DEFAULT_IPMI_I2C];
  ECCLESIA_ASSIGN_OR_RETURN(
      std::vector<std::unique_ptr<I2cSensorAssemblyFruInfo>>
          sensor_assembly_frus,
      fru_scanner_ipmi_i2c->ScanAllI2cSensorAssemblyFru());
  DLOG(INFO) << "Deterministic BMC: Scanning FRUs with deterministic FRU "
                "scanner for sensor assembly FRU: "
             << sensor_assembly_frus.size();
  for (const auto& fru_info : sensor_assembly_frus) {
    DLOG(INFO) << "Deterministic BMC: Scanning FRUs with deterministic FRU "
                  "scanner for sensor assembly FRU: "
               << fru_info->expected_barepath;
    Fru fru;
    Attributes* attributes = fru.mutable_attributes();
    attributes->mutable_expected_hardware_info()->set_expected_barepath(
        fru_info->expected_barepath);
    if (fru_info->present) {
      attributes->set_presence_status(PresenceStatus::PRESENCE_STATUS_PRESENT);
    } else {
      attributes->set_presence_status(
          PresenceStatus::PRESENCE_STATUS_NOT_FOUND);
    }
    fru_table.mutable_key_to_fru()->insert({fru_info->expected_barepath, fru});
  }

  // TODO: b/509637698 - Migrate after the new model is ready.
  if (options_.fru_scanners.contains(SCANNER_TYPE_GPIO)) {
    auto& fru_scanner_gpio = options_.fru_scanners[SCANNER_TYPE_GPIO];
    ECCLESIA_ASSIGN_OR_RETURN(
        std::vector<std::unique_ptr<GpioFruInfo>> gpio_frus,
        fru_scanner_gpio->ScanAllGpioFrus());
    for (const auto& fru_info : gpio_frus) {
      Fru fru;
      Attributes* attributes = fru.mutable_attributes();
      attributes->mutable_expected_hardware_info()->set_expected_barepath(
          fru_info->expected_barepath);
      attributes->set_presence_status(fru_info->presence_status);
      fru_table.mutable_key_to_fru()->insert(
          {fru_info->expected_barepath, fru});
    }
  }

  // TODO: b/526494991 - Migrate after the new model is ready.
  if (options_.fru_scanners.contains(SCANNER_TYPE_USB)) {
    auto& fru_scanner_usb = options_.fru_scanners[SCANNER_TYPE_USB];
    ECCLESIA_ASSIGN_OR_RETURN(std::vector<std::unique_ptr<UsbFruInfo>> usb_frus,
                              fru_scanner_usb->ScanAllUsbFrus());
    for (const auto& fru_info : usb_frus) {
      Fru fru;
      Attributes* attributes = fru.mutable_attributes();
      attributes->mutable_expected_hardware_info()->set_expected_barepath(
          fru_info->expected_barepath);
      attributes->set_presence_status(fru_info->presence_status);
      fru_table.mutable_key_to_fru()->insert(
          {fru_info->expected_barepath, fru});
    }
  }

  // Scan all I2C eeprom FRUs with the default IPMI I2C scanner.
  ECCLESIA_ASSIGN_OR_RETURN(std::vector<std::unique_ptr<I2cFruInfo>> frus,
                            fru_scanner_ipmi_i2c->ScanAllI2cFrus());

  // construct RawFruTable and FruTable by iterating through all FRUs.
  RawFruTable raw_fru_table;

  for (const auto& fru_info : frus) {
    // Construct Fru from I2cFruInfo (Deterministic BMC)
    Fru fru;
    Attributes* attributes = fru.mutable_attributes();
    attributes->set_key(GetFruKey(fru_info->bus, fru_info->address));
    attributes->mutable_expected_hardware_info()->set_expected_barepath(
        fru_info->expected_barepath);
    attributes->mutable_expected_hardware_info()->set_expected_part_number(
        fru_info->expected_part_number);
    attributes->mutable_expected_hardware_info()->set_expected_serial_number(
        fru_info->expected_serial_number);

    fru.mutable_i2c_info()->set_bus(fru_info->bus);
    fru.mutable_i2c_info()->set_address(fru_info->address);

    if (fru_info->parsing_error) {
      LOG(WARNING) << "Parsing error detected for FRU: "
                   << fru_info->expected_barepath
                   << " at bus: " << fru_info->bus
                   << " address: " << fru_info->address
                   << ". Setting presence status to NOT_SCANNED.";
      attributes->set_presence_status(
          PresenceStatus::PRESENCE_STATUS_NOT_SCANNED);
      fru_table.mutable_key_to_fru()->insert({attributes->key(), fru});
      continue;
    }

    if (!fru_info->present) {
      // Nothing to be done for RawFru.
      absl::StatusOr<bool> is_missing_ok_status =
          IsFruMissingOk(fru_info->expected_barepath);
      bool is_missing_ok = false;
      if (is_missing_ok_status.ok()) {
        is_missing_ok = *is_missing_ok_status;
      } else {
        LOG(WARNING) << "Failed to check if FRU is missing ok: "
                     << is_missing_ok_status.status();
      }

      if (is_missing_ok) {
        attributes->set_presence_status(
            PresenceStatus::PRESENCE_STATUS_NOT_SCANNED);
      } else {
        // Mark it FRU as not found.
        attributes->set_presence_status(
            PresenceStatus::PRESENCE_STATUS_NOT_FOUND);
      }
      fru_table.mutable_key_to_fru()->insert({attributes->key(), fru});
      continue;
    }

    // Parse FRU data to get actual part number and serial number for present
    // FRUs.
    absl::flat_hash_map<std::string, std::string> fru_data_fields;
    resCodes res = formatIPMIFRU(fru_info->data, fru_data_fields);
    if (res == resCodes::resErr) {
      return absl::InternalError(
          absl::StrCat("Failed to parse FRU for device at bus: ", fru_info->bus,
                       " address: ", fru_info->address,
                       " with error: ", resCodesToString(res)));
    }
    if (res == resCodes::resWarn) {
      LOG(WARNING) << "Warnings while parsing FRU for device at bus "
                   << fru_info->bus << " address " << fru_info->address
                   << ". You may want to check log for details.";
    }

    // Construct RawFru for present FRUs only. Present FRU is not necessarily
    // valid. So RawFruTable will have both expected and illogical present FRUs.
    // This is to align with old non-deterministic logic.
    RawFru raw_fru = CreateAndPopulatePresentRawFru(fru_info, fru_data_fields);
    raw_fru_table.mutable_key_to_raw_fru()->insert({raw_fru.key(), raw_fru});

    if (options_.strict_part_info_check) {
      // Continue to complete the construction of Fru
      auto part_and_serial_number =
          GetPartAndSerialNumberFromFields(fru_data_fields);
      if (!part_and_serial_number.ok()) {
        return absl::InternalError(absl::StrCat(
            "Failed to get part and serial number for device at bus: ",
            fru_info->bus, " address: ", fru_info->address,
            " with error: ", part_and_serial_number.status()));
      }

      std::string actual_part_number = part_and_serial_number->first;
      std::string actual_serial_number = part_and_serial_number->second;

      if (actual_part_number != fru_info->expected_part_number ||
          actual_serial_number != fru_info->expected_serial_number) {
        attributes->set_presence_status(
            PresenceStatus::PRESENCE_STATUS_PRESENT_ILLOGICAL);
      } else {
        attributes->set_presence_status(
            PresenceStatus::PRESENCE_STATUS_PRESENT);
      }
    } else {
      // Mark it FRU as present regardless of the part info.
      attributes->set_presence_status(PresenceStatus::PRESENCE_STATUS_PRESENT);
    }

    fru_table.mutable_key_to_fru()->insert({attributes->key(), fru});
  }

  std::vector<RawFru> new_raw_frus;
  for (const auto& [key, _] : raw_fru_table.key_to_raw_fru()) {
    if (!ContainsFru(key)) {
      new_raw_frus.push_back(raw_fru_table.key_to_raw_fru().at(key));
    }
  }
  SetFruTable(std::move(raw_fru_table));
  // TODO(b/484338308): Update FruTable and TopologyConfig in EntityConfig for
  // dBMC redfish conformity.
  // GetEntityConfig()->UpdateFruAndTopology(GetCopyOfCurrentScannedFrus(),
  //                                         new_raw_frus);

  return fru_table;
}

absl::Status FruCollector::ScanDeterministicallyAndUpdateFruTable() {
  ECCLESIA_ASSIGN_OR_RETURN(FruTable fru_table, ScanAllFrusDeterministically());
  SetDeterministicFruTable(std::move(fru_table));
  return absl::OkStatus();
}

void FruCollector::SetUpAdHocFruScanning() {
  if (options_.fru_scanners.empty()) {
    LOG(WARNING) << "FruScanners is empty";
    return;
  }

  LOG(INFO) << "Number of available fru_scanners: "
            << options_.fru_scanners.size();
  for (const auto& ad_hoc_fru_config : options_.ad_hoc_fru_scanning_configs) {
    std::string fru_key =
        GetFruKey(ad_hoc_fru_config.hal_common_config().bus(),
                  ad_hoc_fru_config.hal_common_config().address());
    // If the frutable already has the ad-hoc fru, skip it.
    if (ContainsFru(fru_key)) {
      LOG(WARNING) << "FRU key " << fru_key
                   << " already exists, skipping ad-hoc setup for "
                   << ad_hoc_fru_config.name();
      continue;
    }

    // If Ad-hoc FRU config has no periodic scan config, skip it.
    if (ad_hoc_fru_config.periodic_scan_config_size() == 0) {
      LOG(WARNING) << "No periodic_scan_config for " << ad_hoc_fru_config.name()
                   << ", skipping.";
      continue;
    }

    LOG(INFO) << "Scheduling AdHocFruScan for " << ad_hoc_fru_config.name();

    ScheduleAdHocFruScan(ad_hoc_fru_config);
  }
}

void FruCollector::SetUpPeriodicDeterministicFruScanning() {
  if (!options_.enable_deterministic_fru_scanning) {
    LOG(WARNING) << "Deterministic FRU scanning is disabled, skipping periodic "
                    "deterministic FRU scan.";
    return;
  }
  if (!options_.enable_deterministic_periodic_fru_scanning) {
    LOG(WARNING) << "Deterministic BMC is enabled, but Periodic deterministic "
                    "FRU scanning is not enabled, "
                    "skipping.";
    return;
  }
  if (options_.periodic_deterministic_fru_scan_interval_ms <= 0) {
    LOG(WARNING) << "Deterministic BMC periodic scan interval is not positive: "
                 << options_.periodic_deterministic_fru_scan_interval_ms
                 << " ms";
    return;
  }
  LOG(INFO) << "Setting up periodic deterministic FRU scan with interval "
            << options_.periodic_deterministic_fru_scan_interval_ms << " ms";

  absl::MutexLock lock(deterministic_scan_task_id_mutex_);
  if (deterministic_scan_task_id_.has_value()) {
    LOG(WARNING) << "Periodic deterministic FRU scan already scheduled.";
    return;
  }

  deterministic_scan_task_id_ = task_scheduler_->RunAndScheduleAsync(
      [this](absl::AnyInvocable<void()> on_done) {
        if (absl::Status status =
                this->ScanDeterministicallyAndUpdateFruTable();
            !status.ok()) {
          LOG(WARNING) << "Periodic Deterministic FRU scan failed: " << status;
        }
        on_done();
      },
      absl::Milliseconds(options_.periodic_deterministic_fru_scan_interval_ms));
}

void FruCollector::HandleHostOsInactiveToStandby(const std::string& host_id,
                                                 bool setup_run) {
  if (!options_.smbios_inventory) {
    LOG(ERROR) << "HandleHostOsInactiveToStandby: SMBIOS inventory options not "
                  "available. Exiting.";
    return;
  }

  absl::StatusOr<std::vector<std::string>> associated_parts =
      GetAssociatedSmbiosInventoryParts(host_id);
  if (!associated_parts.ok()) {
    LOG(WARNING)
        << "HandleHostOsInactiveToStandby: No configured SMBIOS inventory "
           "parts for host '"
        << host_id
        << "'. Ignoring OS transition from inactive to standby (NO-OP).";
    return;
  }

  HostPollingState* state = GetHostPollingState(host_id);
  if (state == nullptr) {
    LOG(ERROR) << "HandleHostOsInactiveToStandby: HostPollingState not found "
                  "for host '"
               << host_id << "'. Exiting OS transition.";
    return;
  }
  absl::MutexLock lock(state->host_polling_mutex);

  if (state->is_polling) {
    task_scheduler_->Cancel(state->polling_task_id);
  }

  state->is_polling = true;
  state->polling_start_time = options_.clock->Now();

  state->polling_task_id = task_scheduler_->ScheduleOneShotAsync(
      [this, host_id, parts = *associated_parts,
       setup_run](absl::AnyInvocable<void()> on_done) {
        this->PollSmbiosStatus(host_id, parts, setup_run);
        on_done();
      },
      absl::Milliseconds(1));
}

void FruCollector::HandleHostOsStandbyToInactive(const std::string& host_id,
                                                 bool setup_run) {
  if (!options_.smbios_inventory) {
    LOG(ERROR) << "HandleHostOsStandbyToInactive: SMBIOS inventory options not "
                  "available. Exiting.";
    return;
  }

  absl::StatusOr<std::vector<std::string>> associated_parts =
      GetAssociatedSmbiosInventoryParts(host_id);
  if (!associated_parts.ok()) {
    LOG(WARNING)
        << "HandleHostOsStandbyToInactive: No configured SMBIOS inventory "
           "parts for host '"
        << host_id
        << "'. Ignoring OS transition from standby to inactive (NO-OP).";
    return;
  }

  HostPollingState* state = GetHostPollingState(host_id);
  if (state == nullptr) {
    LOG(ERROR) << "HandleHostOsStandbyToInactive: HostPollingState not found "
                  "for host '"
               << host_id << "'. Exiting OS transition.";
    return;
  }

  {
    absl::MutexLock lock(state->host_polling_mutex);
    state->is_polling = false;
    if (state->polling_task_id != -1) {
      task_scheduler_->Cancel(state->polling_task_id);
      state->polling_task_id = -1;
    }
    // Mark the SMBIOS status as consumed. This ensures that any pending "NEW"
    // status is cleared when polling is cancelled. This is important to avoid
    // the possibility of the next boot thinking there is new SMBIOS data when
    // there isn't.
    WriteSmbiosStatusConsumed(host_id);
  }

  {
    absl::MutexLock table_lock(smbios_fru_table_mutex_);
    SetSmbiosInventoryStatus(smbios_fru_table_, *associated_parts,
                             PresenceStatus::PRESENCE_STATUS_NOT_SCANNED);
  }
}

void FruCollector::SetSmbiosInventoryStatus(
    FruTable& table, const std::vector<std::string>& associated_parts,
    PresenceStatus target_status) {
  auto& key_to_fru = *table.mutable_key_to_fru();
  for (const std::string& barepath : associated_parts) {
    auto it = key_to_fru.find(barepath);
    if (it != key_to_fru.end()) {
      it->second.mutable_attributes()->set_presence_status(target_status);
    }
  }
}

void FruCollector::PollSmbiosStatus(
    const std::string& host_id,
    const std::vector<std::string>& associated_parts, bool setup_run) {
  HostPollingState* state = GetHostPollingState(host_id);
  if (state == nullptr) {
    return;
  }
  absl::MutexLock lock(state->host_polling_mutex);
  if (!state->is_polling) {
    return;
  }

  if (options_.clock->Now() - state->polling_start_time > absl::Minutes(2)) {
    LOG(WARNING) << "PollSmbiosStatus: SMBIOS 'NEW' status timeout after 2 "
                    "minutes for host: '"
                 << host_id << "'";
    state->is_polling = false;
    state->polling_task_id = -1;

    // If 2 minutes lapsed after transitioning to standby but we don't see a new
    // blob come, we assume the current blob is the up-to-date one. This is
    // inefficient as it will fail to detect issues where the SMBIOS blob indeed
    // didn't arrive.
    if (setup_run) {
      ExecuteSmbiosUpdate(host_id, associated_parts,
                          /*update_status_file=*/false);
    } else {
      absl::MutexLock table_lock(smbios_fru_table_mutex_);
      SetSmbiosInventoryStatus(smbios_fru_table_, associated_parts,
                               PresenceStatus::PRESENCE_STATUS_NOT_FOUND);
    }
    return;
  }

  bool status_is_new = (ReadSmbiosStatus(host_id) == "NEW");

  if (status_is_new) {
    ExecuteSmbiosUpdate(host_id, associated_parts,
                        /*update_status_file=*/true);
    state->is_polling = false;
    state->polling_task_id = -1;
  } else {
    state->polling_task_id = task_scheduler_->ScheduleOneShotAsync(
        [this, host_id, associated_parts,
         setup_run](absl::AnyInvocable<void()> on_done) {
          this->PollSmbiosStatus(host_id, associated_parts, setup_run);
          on_done();
        },
        absl::Seconds(5));
  }
}

// Returns the isolated SMBIOS binary file path for a specific host ID.
std::string FruCollector::GetSmbiosFilePathForHost(
    const std::string& host_id) const {
  std::string suffix = ExtractHostNumber(host_id);
  if (!suffix.empty()) {
    // Multi-host systems use the host-indexed path.
    return absl::StrCat(options_.smbios_multihost_host_file_path_prefix,
                        suffix);
  }
  // Single-host systems use the default path.
  return options_.smbios_single_host_file_path;
}

void FruCollector::ExecuteSmbiosUpdate(
    const std::string& host_id,
    const std::vector<std::string>& associated_parts, bool update_status_file) {
  absl::StatusOr<platforms::gbmc::hal::SmbiosData> smbios_data;
  if (host_id == "system") {
    smbios_data = options_.smbios_inventory->ReadAndParse();
  } else {
    // multi-host systems use the host specific path.
    std::string target_path = GetSmbiosFilePathForHost(host_id);
    smbios_data = options_.smbios_inventory->ReadAndParse(target_path);
  }
  if (!smbios_data.ok()) {
    LOG(ERROR) << "Failed to read and parse SMBIOS data for host '" << host_id
               << "': " << smbios_data.status();
    // Only mark the components as NOT_FOUND if the SMBIOS blob is explicitly
    // missing. If there is a parsing error (e.g., DataLoss), we leave the
    // status as NOT_SCANNED to avoid falsely reporting absence when the issue
    // might be a transient firmware bug or corrupt data.
    if (absl::IsNotFound(smbios_data.status())) {
      absl::MutexLock table_lock(&smbios_fru_table_mutex_);
      SetSmbiosInventoryStatus(smbios_fru_table_, associated_parts,
                               PresenceStatus::PRESENCE_STATUS_NOT_FOUND);
    }
    return;
  }

  FruTable local_table = GetCopyOfSmbiosFruTable();

  SetSmbiosInventoryStatus(local_table, associated_parts,
                           PresenceStatus::PRESENCE_STATUS_NOT_FOUND);

  ProcessSmbiosCpu(associated_parts, smbios_data->cpus, local_table);
  ProcessSmbiosDimm(associated_parts, smbios_data->dimms, local_table);

  {
    absl::MutexLock table_lock(smbios_fru_table_mutex_);
    for (const std::string& barepath : associated_parts) {
      auto it = local_table.key_to_fru().find(barepath);
      if (it != local_table.key_to_fru().end()) {
        (*smbios_fru_table_.mutable_key_to_fru())[barepath] = it->second;
      }
    }
  }

  if (update_status_file) {
    WriteSmbiosStatusConsumed(host_id);
  }
}

void FruCollector::ProcessSmbiosCpu(
    const std::vector<std::string>& associated_parts,
    const std::vector<platforms::gbmc::hal::SmbiosCpuInfo>& cpus,
    FruTable& fru_table) {
  for (const auto& info : cpus) {
    if (!info.socket_designation.has_value()) {
      continue;
    }

    // Check bit 6 (0x40) of the status field to determine CPU presence.
    // Spec: google3/gbmc-hal/docs/specs/dsp0134-smbios-v3-9-0-spec.md
    // Note for future reference: Bits 0-2 (0x07) indicate the CPU Status
    // (1 = Enabled, other values = Disabled/Unknown/etc). Currently, we
    // only need to collect presence, so we don't evaluate the functional state.
    if (!info.status.has_value() || (*info.status & 0x40) == 0) {
      continue;
    }

    std::string designation = *info.socket_designation;

    // The key is the barepath of the FRU, e.g., `/phys/CPU0` or
    // `/phys/PE0/CPU1`. The designation/locator from SMBIOS might be just
    // `CPU0` or `CPU1`. We use `EndsWith` to match the FRU.

    // Multi-host & Single-host: Only search and match keys associated with this
    // host
    auto& key_to_fru = *fru_table.mutable_key_to_fru();
    for (const std::string& key : associated_parts) {
      auto it = key_to_fru.find(key);
      if (it != key_to_fru.end() && absl::EndsWith(key, designation)) {
        Fru& fru = it->second;
        fru.mutable_attributes()->set_presence_status(
            PresenceStatus::PRESENCE_STATUS_PRESENT);
        auto* cpu = fru.mutable_data()->mutable_processor_info();
        if (info.cpuid_x86_stepping) {
          cpu->set_stepping(std::to_string(*info.cpuid_x86_stepping));
        }
        break;
      }
    }
  }
}

void FruCollector::ProcessSmbiosDimm(
    const std::vector<std::string>& associated_parts,
    const std::vector<platforms::gbmc::hal::SmbiosDimmInfo>& dimms,
    FruTable& fru_table) {
  for (const auto& info : dimms) {
    if (!info.device_locator.has_value()) {
      continue;
    }

    // An absent, unpopulated, or empty DIMM will yield size_bytes = 0.
    // Spec: google3/gbmc-hal/docs/specs/dsp0134-smbios-v3-9-0-spec.md
    if (!info.size_bytes.has_value() || *info.size_bytes <= 0) {
      continue;
    }

    // Additionally, check for "NO DIMM" in manufacturer or part number.
    if (info.manufacturer &&
        absl::StrContains(absl::AsciiStrToUpper(*info.manufacturer),
                          "NO DIMM")) {
      continue;
    }
    if (info.part_number &&
        absl::StrContains(absl::AsciiStrToUpper(*info.part_number),
                          "NO DIMM")) {
      continue;
    }

    std::string locator = *info.device_locator;

    // The key is the barepath of the FRU, e.g., `/phys/DIMM0` or
    // `/phys/PE0/DIMM1`. The designation/locator from SMBIOS might be just
    // `DIMM0` or `DIMM1`. We use `EndsWith` to match the FRU.

    // Multi-host & Single-host: Only search and match keys associated with this
    // host
    auto& key_to_fru = *fru_table.mutable_key_to_fru();
    for (const std::string& key : associated_parts) {
      auto it = key_to_fru.find(key);
      if (it != key_to_fru.end() && absl::EndsWith(key, locator)) {
        Fru& fru = it->second;
        fru.mutable_attributes()->set_presence_status(
            PresenceStatus::PRESENCE_STATUS_PRESENT);
        auto* mem = fru.mutable_data()->mutable_memory_info();
        if (info.manufacturer) {
          mem->set_manufacturer(*info.manufacturer);
        }
        if (info.serial_number) {
          mem->set_serial_number(*info.serial_number);
        }
        if (info.part_number) {
          mem->set_part_number(*info.part_number);
        }
        if (info.size_bytes) {
          mem->set_capacity_mib(
              static_cast<int64_t>(*info.size_bytes / (1024 * 1024)));
        }
        break;
      }
    }
  }
}

std::string FruCollector::GetSmbiosStatusFilePathForHost(
    const std::string& host_id) const {
  std::string suffix = ExtractHostNumber(host_id);
  if (!suffix.empty()) {
    return absl::StrCat(options_.smbios_multihost_host_status_file_path_prefix,
                        suffix);
  }
  return options_.smbios_single_host_status_file_path;
}

std::string FruCollector::ReadSmbiosStatus(const std::string& host_id) const {
  std::string final_path = GetSmbiosStatusFilePathForHost(host_id);
  std::ifstream status_file(final_path);
  if (status_file) {
    std::string status;
    status_file >> status;
    return status;
  }
  return "";
}

void FruCollector::WriteSmbiosStatusConsumed(const std::string& host_id) const {
  // Update the status file to "Consumed" to indicate that the SMBIOS data has
  // been consumed. We write to a temporary file and rename it to ensure
  // atomicity.
  std::string final_path = GetSmbiosStatusFilePathForHost(host_id);
  std::string tmp_status_file_path = final_path + ".bmcweb.tmp";
  std::ofstream status_file(tmp_status_file_path, std::ios::trunc);
  if (status_file) {
    status_file << "Consumed";
    status_file.close();
    std::error_code ec;
    std::filesystem::rename(tmp_status_file_path, final_path, ec);
    if (ec) {
      LOG(ERROR) << "Failed to atomically rename status file: " << ec.message();
    }
  }
}

FruCollector::FruCollector(
    Options options, RawFruTable fru_table,
    std::shared_ptr<TaskScheduler> task_scheduler,
    absl::flat_hash_map<RelatedState, std::unique_ptr<ResourceStateManager>>
        resource_state_managers)
    : task_scheduler_(std::move(task_scheduler)),
      options_(std::move(options)),
      fru_table_(std::move(fru_table)),
      fru_barepath_to_related_state_(
          std::move(options_.fru_barepath_to_related_state)),
      host_to_smbios_inventory_parts_(
          std::move(options_.host_to_smbios_inventory_parts)),
      resource_state_managers_(std::move(resource_state_managers)) {
  InitializeSmbiosPollingStates();
  InitializeExpectedSmbiosComponents();
}

void FruCollector::InitializeSmbiosPollingStates() {
  for (const auto& [host_id, _] : host_to_smbios_inventory_parts_) {
    host_polling_states_[host_id] = std::make_unique<HostPollingState>();
  }
}

void FruCollector::InitializeExpectedSmbiosComponents() {
  absl::MutexLock lock(smbios_fru_table_mutex_);
  for (const auto& component : options_.expected_smbios_components) {
    Fru fru;
    fru.mutable_attributes()
        ->mutable_expected_hardware_info()
        ->set_expected_barepath(component.barepath());
    fru.mutable_attributes()->set_presence_status(
        PresenceStatus::PRESENCE_STATUS_NOT_SCANNED);
    smbios_fru_table_.mutable_key_to_fru()->insert({component.barepath(), fru});
  }
}

FruCollector::HostPollingState* FruCollector::GetHostPollingState(
    const std::string& host_id) const {
  auto it = host_polling_states_.find(host_id);
  if (it != host_polling_states_.end()) {
    return it->second.get();
  }
  return nullptr;
}

std::unique_ptr<FruCollector> EmptyFruCollector::Create() {
  return std::make_unique<EmptyFruCollector>();
}

absl::StatusOr<FruTable> EmptyFruCollector::ScanAllFrusDeterministically() {
  return absl::UnimplementedError(
      "EmptyFruCollector::ScanAllFrusDeterministically is called. This is "
      "unimplemented.");
}

absl::Status EmptyFruCollector::ScanDeterministicallyAndUpdateFruTable() {
  return absl::UnimplementedError(
      "EmptyFruCollector::ScanDeterministicallyAndUpdateFruTable is called. "
      "This is unimplemented.");
}

RawFruTable EmptyFruCollector::GetCopyOfCurrentScannedFrus() const
    ABSL_LOCKS_EXCLUDED(fru_table_mutex_) {
  LOG(WARNING) << "EmptyFruCollector::GetCopyOfCurrentScannedFrus is called. "
                  "returning empty RawFruTable.";
  return RawFruTable();
}

FruTable EmptyFruCollector::GetCopyOfSmbiosFruTable() const
    ABSL_LOCKS_EXCLUDED(smbios_fru_table_mutex_) {
  LOG(WARNING) << "EmptyFruCollector::GetCopyOfSmbiosFruTable is called. "
                  "returning empty FruTable.";
  return FruTable();
}

FruTable EmptyFruCollector::GetCopyOfDeterministicFruTable() const
    ABSL_LOCKS_EXCLUDED(deterministic_fru_table_mutex_) {
  LOG(WARNING)
      << "EmptyFruCollector::GetCopyOfDeterministicFruTable is called. "
         "returning empty FruTable.";
  return FruTable();
}

nlohmann::json EmptyFruCollector::ToJson() const {
  return nlohmann::json::parse("{\"Warning\": \"EmptyFruCollector used.\"}");
}

void EmptyFruCollector::SetEntityConfig(
    const std::shared_ptr<EntityConfig>& entity_config)
    ABSL_LOCKS_EXCLUDED(entity_config_mutex_) {
  LOG(WARNING) << "EmptyFruCollector::SetEntityConfig is called. This is a "
                  "no-op.";
}

std::shared_ptr<EntityConfig> EmptyFruCollector::GetEntityConfig() const {
  return nullptr;
}

absl::Status EmptyFruCollector::ConfigureDeterministicCollection(
    const Config& config) {
  return absl::UnimplementedError(
      "EmptyFruCollector::ConfigureDeterministicCollection is called. This is "
      "not "
      "implemented.");
}

absl::Status FruCollector::ConfigureDeterministicCollection(
    const Config& config) {
  if (config.sampling_interval_ms < 0) {
    return absl::InvalidArgumentError("Invalid sampling interval");
  }

  if (!options_.enable_deterministic_fru_scanning) {
    LOG(WARNING) << "Deterministic FRU scanning is disabled, "
                    "ConfigureCollection has no effect.";
    return absl::OkStatus();
  }

  // Eagerly trigger a deterministic scan so HFT clients receive an initial
  // frame with fresh data right at subscription time without waiting 30
  // seconds.
  if (absl::Status status = ScanDeterministicallyAndUpdateFruTable();
      !status.ok()) {
    LOG(WARNING) << "Initial deterministic FRU scan failed: " << status;
  }

  // on change is what we want, so this method will not be called eventually.
  LOG(WARNING) << "Deterministic FRU scanning is enabled, but dynamic "
                  "configuration of the periodic scan interval is not "
                  "supported. The provided sampling interval of "
               << config.sampling_interval_ms << " ms will be ignored.";
  return absl::OkStatus();
}

const absl::flat_hash_map<RelatedState, std::unique_ptr<ResourceStateManager>>&
EmptyFruCollector::GetResourceStateManagers() const {
  return resource_state_managers_;
}

nlohmann::json EmptyFruCollector::GetSchedulerStats() const {
  return nlohmann::json::parse("{\"Warning\": \"EmptyFruCollector used.\"}");
}

std::size_t EmptyFruCollector::GetAllUserTaskCount() const { return 0; }

}  // namespace milotic_tlbmc
