#include "bmc/state_monitor_bmc.h"

#include <cstdint>
#include <memory>
#include <string>
#include <utility>

#include "one/node_entities_api.pb.h"
#include "bmc/address_lookup.h"
#include "bmc/daemon_context_bmc.h"
#include "bmc/redfish.h"
#include "daemon_context.h"
#include "safepower_agent.pb.h"
#include "safepower_agent_config.pb.h"
#include "state_updater.h"
#include "static_state.h"
#include "one/resolved_entities.pb.h"
#include "absl/functional/bind_front.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "nlohmann/json.hpp"
#include "nlohmann/json_fwd.hpp"
#include "bmc/status_macros.h"

namespace safepower_agent {

using safepower_agent_config::GpowerdConfig;
using safepower_agent_config::StateGatheringInfo;

static void GetBootNumCallback(StaticStateLoader::GetStateCallback callback,
                               absl::StatusOr<nlohmann::json> js) {
  if (!js.ok()) {
    callback(js.status());
    return;
  }
  auto boot_info = js->find("BootInfo");
  if (boot_info == js->end()) {
    callback(absl::NotFoundError(
        absl::StrCat("BootInfo not found in ", js->dump())));
    return;
  }
  if (!boot_info->is_object()) {
    callback(absl::InvalidArgumentError(
        absl::StrCat("BootInfo is not an object in ", js->dump())));
    return;
  }
  auto boot_num = boot_info->find("BootCount");
  if (boot_num == boot_info->end()) {
    callback(absl::NotFoundError(
        absl::StrCat("BootCount not found in ", js->dump())));
    return;
  }
  auto* boot_num_int = boot_num->get_ptr<int64_t*>();
  if (boot_num_int == nullptr) {
    callback(absl::InvalidArgumentError(
        absl::StrCat("BootCount is not an int64_t in ", js->dump())));
    return;
  }
  absl::string_view entity_tag =
      DaemonContext::Get().offline_node_entities().entity_tag();
  safepower_agent_proto::SystemState state;
  (*state.mutable_node_state())[entity_tag]
      .mutable_boot_state()
      ->set_boot_counter(*boot_num_int);
  callback(state);
}

StateMonitorBMC::StateMonitorBMC(
    std::shared_ptr<StateUpdater<safepower_agent_proto::SystemState>> reactor)
    : reactor_(reactor) {}

absl::Status StateMonitorBMC::InitializeBootnumLoader(
    const GpowerdConfig& config) {
  if (DaemonContext::Get().offline_node_entities().entity_tag().empty()) {
    return absl::FailedPreconditionError(
        "offline_node_entities is not initialized in DaemonContext: No "
        "entity_tag found");
  }
  if (bootnum_loader_.has_value()) {
    return absl::InternalError("StateMonitorBMC already initialized");
  }
  StaticStateLoaderConfig loader_config = {
      .retry_interval = absl::Milliseconds(
          config.redfish_boot_count_config().retry_interval_ms()),
      .max_retries = -1,
  };
  if (config.redfish_boot_count_config().has_timeout_sec()) {
    loader_config.timeout =
        absl::Seconds(config.redfish_boot_count_config().timeout_sec());
  }
  bootnum_loader_.emplace(
      "bootnum_loader",
      [c = config.redfish_boot_count_config()](
          StaticStateLoader::GetStateCallback callback) {
        LOG(INFO) << "Attempting to get bootnum from " << c.ip() << ":"
                  << c.port() << c.uri();
        Redfish::Get(c.uri(),
                     absl::bind_front(&GetBootNumCallback, std::move(callback)),
                     c.ip(), c.port());
      },
      reactor_, loader_config);
  return absl::OkStatus();
}

absl::Status StateMonitorBMC::BuildFromConfig(const GpowerdConfig& config) {
  if (config.has_ping_config()) {
    RETURN_IF_ERROR(CreateIMCPingMonitor());
  }
  RETURN_IF_ERROR(InitializeBootnumLoader(config));
  for (auto& resource_to_monitor : config.state_monitor_config()) {
    if (resource_to_monitor.state_gathering_info().info_case() ==
        StateGatheringInfo::kRedfish) {
      std::string state_name(resource_to_monitor.state_name());
      std::string uri(
          resource_to_monitor.state_gathering_info().redfish().uri());
      std::string json_key(
          resource_to_monitor.state_gathering_info().redfish().json_key());
      std::string node_entity_tag(
          resource_to_monitor.system_component().node_entity_tag());
      uint64_t collection_interval_ms =
          resource_to_monitor.state_gathering_info().collection_interval_ms();
      auto prototype = resource_to_monitor.state_gathering_info().prototype();
      if (prototype.has_power_state() &&
          (prototype.power_state().has_state())) {
        // create bmcweb state monitor for power state
        if (!CreateRedfishUpdatePowerState(state_name, uri, json_key,
                                           collection_interval_ms,
                                           node_entity_tag)
                 .ok()) {
          LOG(ERROR) << "failed to create bmcweb state monitor for: "
                     << state_name;
          return absl::InvalidArgumentError(
              "failed to create bmcweb state monitor for: " + state_name);
        }
      } else {
        LOG(ERROR) << "update function is not supported  TODO b/372971177";
        return absl::UnimplementedError("update function is not supported ");
      }
    } else if (resource_to_monitor.state_gathering_info().info_case() ==
               StateGatheringInfo::kDbus) {
      (void)CreateDbusStateMonitor("", "", "", "", "", 1000);
    } else {
      LOG(ERROR) << "state monitor type is not supported; "
                 << resource_to_monitor.state_gathering_info().info_case();
      return absl::InvalidArgumentError(
          absl::StrCat("state monitor type is not supported: ",
                       resource_to_monitor.state_gathering_info().info_case()));
    }
  }
  return absl::OkStatus();
}

void StateMonitorBMC::InsertPingStateMonitor(
    std::string node_entity_tag, absl::StatusOr<std::string> ip_address) {
  if (!ip_address.ok()) {
    LOG(ERROR) << "Failed to lookup address for node: " << node_entity_tag
               << " with status: " << ip_address.status();
    return;
  }
  LOG(INFO) << "creating ping state monitor for: " << node_entity_tag;

  ping_state_monitors_.emplace_back(
      std::move(node_entity_tag), *std::move(ip_address),
      DaemonContext::Get().config().gpowerd_config().ping_config(), reactor_);
  absl::Status status = ping_state_monitors_.back().Start();
  if (!status.ok()) {
    LOG(DFATAL) << "Failed to start ping state monitor for "
                << ping_state_monitors_.back().node_entity_tag() << ": "
                << status;
  }
}

absl::Status StateMonitorBMC::CreateIMCPingMonitor() {
  LOG(INFO) << "Creating ping state monitors";
  if (!DaemonContext::Get().offline_node_entities().has_resolved_config()) {
    return absl::FailedPreconditionError(
        "offline_node_entities is not initialized in DaemonContext: No "
        "resolved_config found");
  }
  for (const auto& [node_entity_tag, node_entity] : DaemonContext::Get()
                                                        .offline_node_entities()
                                                        .resolved_config()
                                                        .entities()) {
    if (node_entity.node_type_info().os_type() ==
            net_model_unm::proto::NOST_NODEOS &&
        node_entity.node_type_info().is_control()) {
      LookupAddress(node_entity_tag,
                    absl::bind_front(&StateMonitorBMC::InsertPingStateMonitor,
                                     this, node_entity_tag));
    }
  }
  return absl::OkStatus();
}

absl::Status StateMonitorBMC::CreateRedfishUpdatePowerState(
    std::string state_name, std::string uri, std::string json_key,
    int collection_interval_ms, std::string node_entity_tag) {
  LOG(INFO) << "creating bmcweb state monitor for:" << state_name;
  LOG(INFO) << "uri: " << uri;
  LOG(INFO) << "json_key: " << json_key;
  LOG(INFO) << "collection_interval_ms: " << collection_interval_ms;

  return DaemonContextBMC::Get().scheduler().PeriodicCall(
      [state_name, uri, json_key, this, node_entity_tag] {
        Redfish::Get(uri, [state_name, uri, json_key, this,
                           node_entity_tag](absl::StatusOr<nlohmann::json> js) {
          if (!js.ok()) {
            LOG(ERROR) << "Failed to get " << uri
                       << " from BMC: " << js.status();
            return;
          }

          auto js_value = js->find(json_key);
          std::string state_str = js_value != js->end() ? *js_value : "";
          safepower_agent_proto::PowerStateSpecifier temp_power_state =
              ConvertStatePowerStringToEnum(state_str);
          const safepower_agent_proto::SystemState current_state =
              this->reactor_->state();

          safepower_agent_proto::PowerStateSpecifier last_ps =
              safepower_agent_proto::POWER_STATE_UNSPECIFIED;
          auto node_it = current_state.node_state().find(node_entity_tag);
          if (node_it != current_state.node_state().end()) {
            last_ps = node_it->second.power_state().state();
          }
          if (last_ps == temp_power_state) return;
          absl::string_view last_ps_str = PowerStateSpecifier_Name(last_ps);
          absl::string_view temp_ps_str =
              PowerStateSpecifier_Name(temp_power_state);
          LOG(INFO) << absl::StrFormat(
              "%s changed from: %d (%s) to: %d (%s)", state_name,
              last_ps, last_ps_str, temp_power_state, temp_ps_str);

          // add new state power state to a new system proto
          safepower_agent_proto::SystemState new_state;
          safepower_agent_proto::PowerState ps;
          ps.set_state(temp_power_state);

          safepower_agent_proto::NodeState ns;
          *(ns.mutable_power_state()) = ps;

          new_state.mutable_node_state()->insert({node_entity_tag, ns});

          reactor_->UpdateState(new_state);
        });
      },
      absl::Milliseconds(collection_interval_ms), state_name);
}

safepower_agent_proto::PowerStateSpecifier
StateMonitorBMC::ConvertStatePowerStringToEnum(absl::string_view state_str) {
  if (state_str == "On") {
    return safepower_agent_proto::POWER_STATE_ON;
  } else if (state_str == "Off") {
    return safepower_agent_proto::POWER_STATE_OFF;
  } else if (state_str == "Paused") {  // not in bmcweb
    return safepower_agent_proto::POWER_STATE_PAUSED;
  } else if (state_str == "PoweringOn") {
    return safepower_agent_proto::POWER_STATE_POWERING_ON;
  } else if (state_str == "PoweringOff") {
    return safepower_agent_proto::POWER_STATE_POWERING_OFF;
  } else {
    LOG(ERROR) << "failed to map power state string to enum: " << state_str;
    return safepower_agent_proto::POWER_STATE_UNSPECIFIED;
  }
}

absl::Status StateMonitorBMC::CreateDbusStateMonitor(
    std::string state_name, std::string dbus_path, std::string dbus_method,
    std::string dbus_interface, std::string dbus_value,
    int collection_interval_ms) {
  LOG(INFO) << "creating dbus state monitor for:" << state_name;
  LOG(INFO) << "dbus_path: " << dbus_path;
  LOG(INFO) << "dbus_method: " << dbus_method;
  LOG(INFO) << "dbus_interface: " << dbus_interface;
  LOG(INFO) << "dbus_value: " << dbus_value;
  LOG(INFO) << "collection_interval_ms: " << collection_interval_ms;
  return absl::UnimplementedError("CreateDbusStateMonitor is not implemented");
}

}  // namespace safepower_agent
