#include "bmc/state_monitor_bmc.h"

#include <safepower_agent_config.pb.h>

#include <any>
#include <filesystem> // NOLINT
#include <fstream>
#include <string>
#include <unordered_map>
#include <utility>

#include "nlohmann/json.hpp"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"

#include "safepower_agent.pb.h"
#include "state_updater.h"


#include "bmc/redfish.h"
#include "absl/base/log_severity.h"
#include "absl/log/log.h"

#include "bmc/daemon_context_bmc.h"

namespace safepower_agent {

using safepower_agent_config::SafePowerAgentConfig;
using safepower_agent_config::GpowerdConfig;
using safepower_agent_config::StateMonitorConfig;
using safepower_agent_config::StateGatheringInfo;
using safepower_agent_config::RedfishInfo;
using safepower_agent_config::DbusInfo;

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();
      std::string component_name = resource_to_monitor.system_component()
          .name();
      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,
          component_name).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
          ("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,
                                                    std::string component_name)
    {
  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, component_name] {
       Redfish::Get(uri,
                    [state_name, uri, json_key, this,
                    node_entity_tag, component_name]
                    (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()){
          auto component_it = node_it->second.component_state().
                find(component_name);
          if (component_it != node_it->second.component_state().end()){
            last_ps = component_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::ComponentState cs;
        *(cs.mutable_power_state()) = ps;

        safepower_agent_proto::NodeState ns;
        ns.mutable_component_state()->insert({component_name, cs});
        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
