#include "bmc/state_monitor_bmc.h"

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

#include "bmc/daemon_context_bmc.h"
#include "bmc/redfish.h"
#include "safepower_agent.pb.h"
#include "safepower_agent_config.pb.h"
#include "state_updater.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"

namespace safepower_agent {

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

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

absl::Status StateMonitorBMC::BuildFromConfig(const GpowerdConfig& 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();
}

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(
              "state changed from: %d (%s) to: %d (%s)", 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
