// gpowerd is a the safe power local agent  for BMC.
// It  implements the SafePowerLocalAgent service, andis responsible for
// actuating power cycles on the machine.

#include <fmt/format.h>
#include <grpcpp/grpcpp.h>
#include <grpcpp/ext/proto_server_reflection_plugin.h>
#include <safepower_agent_config.pb.h>

#include <string>
#include <string_view>
#include <csignal>

#include "action_context.h"
#include "bmc/auth.h"
#include "bmc/daemon_context_bmc.h"
#include "daemon_context.h"
#include "safepower_agent.h"
#include "safepower_agent.pb.h"
#include "state_change_reactor.h"
#include "state_updater.h"
#include "parse_text_proto.h"
#include "bmc/state_monitor_bmc.h"
#include "bmc/status_macros.h"
#include "bmc/register_actions_bmc.h"
#include "bmc/proto_reader.h"

#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "absl/log/log.h"
#include "absl/log/globals.h"

using grpc::Server;
using grpc::ServerBuilder;
using safepower_agent::StateChangeWriteReactor;
using safepower_agent::SafepowerLocalAgentImpl;
using safepower_agent::StateUpdater;
using safepower_agent::DaemonContextBMC;
using safepower_agent::RegisterActionFromConfig;

using safepower_agent_config::SafePowerAgentConfig;

using ::grpc::experimental::AuthorizationPolicyProviderInterface;

const char* address = "[::]:20120";

ABSL_FLAG(std::string, config_file, "/etc/gpowerd/gpowerd_config.proto",
          "proto config file for gpowerd");

// The built-in log flags are not being pulled into this code because the cmake
// build does not include the flags library for logging, so a local flag was
// setup to mitigate this.

// Global log verbosity level. Default is 0.
ABSL_FLAG(int, v, 0, "Global log verbosity level");

absl::Status main_gpowerd()
{
    DaemonContextBMC context;  // only use  DaemonContextBMC::Get()
    [[maybe_unused]] auto& daemon_context =
        DaemonContextBMC::Get();

    safepower_agent_proto::SystemState initialState;
    auto reactor =
        std::make_shared<StateUpdater<safepower_agent_proto::SystemState>>(
            std::move(initialState), true);
    auto action_context_manager =
        std::make_unique<safepower_agent::ActionContextManager>(reactor);

    auto state_monitor = std::make_shared
        <safepower_agent::StateMonitorBMC>(reactor);

    std::string config_file = absl::GetFlag(FLAGS_config_file);

    ASSIGN_OR_RETURN(std::string config_proto_str,
        proto_reader::ReadBinaryFile(config_file));
    LOG(INFO) << "config file contents: " << config_proto_str;

    ASSIGN_OR_RETURN(SafePowerAgentConfig safepower_config,
         safepower_agent::ParseTextProto<SafePowerAgentConfig>
                     (config_proto_str));
    LOG(INFO) << "Config read";


    RETURN_IF_ERROR(state_monitor->BuildFromConfig(
        safepower_config.gpowerd_config()));
    LOG(INFO) << "State monitor built";

    RETURN_IF_ERROR(RegisterActionFromConfig(
        action_context_manager.get(), safepower_config));
    LOG(INFO) << "Actions registered";

    SafepowerLocalAgentImpl safePowerService(std::move(reactor),
                                             std::move(action_context_manager));
    ServerBuilder builder;

    ASSIGN_OR_RETURN(std::shared_ptr<grpc::ServerCredentials>
                     creds, auth::GetCredsInfo());
    LOG(INFO) << "Credentials loaded";

    ASSIGN_OR_RETURN(std::shared_ptr<AuthorizationPolicyProviderInterface>
                     policy, auth::GetAuthPolicy());
    LOG(INFO) << "authorization policy loaded";

    builder.experimental().SetAuthorizationPolicyProvider(policy);

    LOG(INFO) << "using address " << address;
    builder.AddListeningPort(address, creds);

    /* Listen on the given address with an authentication mechanism. */
    builder.RegisterService(&safePowerService);
    grpc::reflection::InitProtoReflectionServerBuilderPlugin();

    std::unique_ptr<Server> server(builder.BuildAndStart());
    if (server == nullptr)
    {
      // TODO Add logic to restarting safePowerService, while running events
      // in the scheduler. (Possibly schedule a retry.)
      LOG(ERROR) << "grpc server failed to start, exiting gPowerD";
      return absl::InternalError
          ("grpc server failed to start, exiting gPowerD");
    }

    // register SIGTERM handler before starting io loop
    std::signal(SIGTERM, [](int) {
      LOG(INFO) << "Received SIGTERM, starting shutting down gracefully";

      absl::Status status = DaemonContextBMC::Get().scheduler().Shutdown();
      if (!status.ok()) {
          LOG(ERROR) << "SIGTERM, shutting down error : " << status;
      }
    });

    LOG(INFO) << "gPowerD started";
    DaemonContextBMC::Get().get_io_context().run();
    LOG(INFO) << "event loop returned";
    if (server){
         server->Shutdown(gpr_now(GPR_CLOCK_MONOTONIC));
    }
    LOG(INFO) << "gPowerD stopped; grpc server shutdown";
    return absl::OkStatus();
}


int main(int argc, char** argv)
{
  absl::ParseCommandLine(argc, argv);
  (void)absl::SetGlobalVLogLevel(absl::GetFlag(FLAGS_v));
  absl::Status status = main_gpowerd();
  if (!status.ok()){
    LOG(ERROR) << "gpowerd exited with status: " << status;
    return 1;
  }
  LOG(INFO) << "gpowerd exited with status: 0 ";
  return 0;
}
