#include "safepower_agent.h"

#include <memory>
#include <utility>

#include "action_context.h"
#include "safepower_agent.pb.h"
#include "state_change_reactor.h"
#include "bmc/convert_status.h"
#include "absl/base/nullability.h"
#include "absl/log/log.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "grpcpp/server_context.h"
#include "grpcpp/support/server_callback.h"
#include "grpcpp/support/status.h"

namespace safepower_agent {
using safepower_agent_proto::ActionStateLog;
using safepower_agent_proto::SystemState;

grpc::ServerUnaryReactor* SafepowerLocalAgentImpl::StartAction(
    grpc::CallbackServerContext* context,
    const safepower_agent_proto::StartActionRequest* request,
    safepower_agent_proto::StartActionResponse* response) {
  grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
  absl::StatusOr<absl::Nonnull<ActionContext*>> action_context =
      action_context_manager_->StartAction(*request);
  if (!action_context.ok()) {
    LOG(ERROR) << "Failed to start action: " << action_context.status();
  } else {
    response->set_response_id(action_context.value()->action_id());
    LOG(INFO) << "Started action " << action_context.value()->action_id()
              << " with request " << request;
  }
  reactor->Finish(ConvertStatus(action_context.status()));
  return reactor;
}

grpc::ServerWriteReactor<safepower_agent_proto::ActionStateLog>*
SafepowerLocalAgentImpl::MonitorAction(
    grpc::CallbackServerContext* /*context*/,
    const safepower_agent_proto::MonitorActionRequest* request) {
  auto reactor = std::make_unique<StateChangeWriteReactor<ActionStateLog>>();
  absl::Nullable<ActionContext*> action_context =
      action_context_manager_->GetActionContext(request->response_id());
  if (action_context == nullptr) {
    LOG(ERROR) << "Action " << request->response_id() << " not found";
    reactor->Finish(
        {grpc::StatusCode::NOT_FOUND,
         absl::StrCat("Action ", request->response_id(), " not found")});
    return StateChangeWriteReactor<ActionStateLog>::Detach(std::move(reactor));
  }
  reactor->Connect(action_context->action_state_updater());
  return StateChangeWriteReactor<safepower_agent_proto::ActionStateLog>::Detach(
      std::move(reactor));
}

grpc::ServerWriteReactor<SystemState>* SafepowerLocalAgentImpl::MonitorState(
    grpc::CallbackServerContext* /*context*/,
    const safepower_agent_proto::MonitorStateRequest* /*request*/) {
  auto reactor = std::make_unique<
      StateChangeWriteReactor<safepower_agent_proto::SystemState>>();
  reactor->Connect(system_state_updater_);
  return StateChangeWriteReactor<safepower_agent_proto::SystemState>::Detach(
      std::move(reactor));
}

grpc::ServerUnaryReactor* SafepowerLocalAgentImpl::GetSupportedActions(
    grpc::CallbackServerContext* context,
    const safepower_agent_proto::GetSupportedActionsRequest* /*request*/,
    safepower_agent_proto::GetSupportedActionsResponse* response) {
  grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
  action_context_manager_->GetSupportedActions(*response);
  reactor->Finish(grpc::Status::OK);
  return reactor;
}

}  // namespace safepower_agent
