#include "boottime_callback.h"

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

#include "boottime.grpc.pb.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/time/time.h"
#include "boottime_api/boottime_api_common.h"
#include "boottime_api/node_config.h"
#include "boottime_api/resource.h"
#include "grpcpp/server_context.h"
#include "grpcpp/support/server_callback.h"
#include "grpcpp/support/status.h"

namespace blobs {

namespace btm = boot_time_monitor;

grpc::Status BootTimeServiceImpl::ToGrpcStatus(absl::Status s) {
  if (s.ok()) {
    return grpc::Status::OK;
  }
  // The grpc & absl code have 1:1 mapping from 0 (OK) to 15 (DATA_LOSS).
  grpc::StatusCode code = static_cast<grpc::StatusCode>(s.code());
  if (code > grpc::StatusCode::DATA_LOSS) {
    code = grpc::StatusCode::UNKNOWN;
  }
  return grpc::Status(static_cast<grpc::StatusCode>(s.code()),
                      std::string(s.message()));
}

absl::Status BootTimeServiceImpl::RegisterSelfToApi() {
  if (base_path_.empty()) {
    // Using default FileResource path
    return boottime_api_.RegisterNode(node_config_);
  } else {
    // Using custom base path
    auto resource = std::make_unique<btm::resource::FileResource>(
        node_config_.node_name,
        base_path_ + std::string(btm::def::kDataDir));
    return boottime_api_.RegisterNode(node_config_, std::move(resource));
  }
}

BootTimeServiceImpl::BootTimeServiceImpl(int instance)
    : phosphor::boottime::grpc_gen::BootTimeService::CallbackService(),
      instance_number_(instance),
      base_path_(),
      node_config_("host" + std::to_string(instance),
                   std::string(btm::kBootTimeTagHost)) {
  RegisterSelfToApi().IgnoreError();
}

BootTimeServiceImpl::BootTimeServiceImpl(int instance,
                                         const std::string& basePath)
    : phosphor::boottime::grpc_gen::BootTimeService::CallbackService(),
      instance_number_(instance),
      base_path_(basePath),
      node_config_("host" + std::to_string(instance),
                   std::string(btm::kBootTimeTagHost)),
      boottime_api_(basePath + std::string(btm::def::kLockFile),
                    absl::Seconds(5)) {
  auto resource = std::make_unique<btm::resource::FileResource>(
      node_config_.node_name,
      basePath + std::string(btm::def::kDataDir));
  RegisterSelfToApi().IgnoreError();
}

grpc::ServerUnaryReactor* BootTimeServiceImpl::SetCheckpoint(
    [[maybe_unused]] grpc::CallbackServerContext* context,
    const phosphor::boottime::SetCheckpointRequest* request,
    [[maybe_unused]] phosphor::boottime::SetCheckpointResponse* response) {
  LOG(INFO) << "SetCheckpoint[" << instance_number_
            << "]: name=" << request->name()
            << ", timestamp=" << request->timestamp_ms()
            << ", duration=" << request->duration_ms();

  grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
  // Check request content
  // Note that timestamp or duration is optional and can be 0
  if (request->name().empty() || request->name().length() > 1024) {
    reactor->Finish(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
                                 "Invalid name length"));
    return reactor;
  }

  absl::Status ret = boottime_api_.SetNodeCheckpoint(
      node_config_, request->name(), request->timestamp_ms(),
      request->duration_ms());
  if (ret.code() == absl::StatusCode::kNotFound) {
    // Retry node register if the node is not found.
    LOG(ERROR) << "Node not found. Retrying node registration.";
    if (!(ret = RegisterSelfToApi()).ok()) {
      reactor->Finish(ToGrpcStatus(ret));
      return reactor;
    }
    ret = boottime_api_.SetNodeCheckpoint(node_config_, request->name(),
                                          request->timestamp_ms(),
                                          request->duration_ms());
  }
  reactor->Finish(ToGrpcStatus(ret));
  return reactor;
}

grpc::ServerUnaryReactor* BootTimeServiceImpl::RebootComplete(
    [[maybe_unused]] grpc::CallbackServerContext* context,
    [[maybe_unused]] const phosphor::boottime::RebootCompleteRequest* request,
    [[maybe_unused]] phosphor::boottime::RebootCompleteResponse* response) {
  LOG(INFO) << "RebootComplete[" << instance_number_ << "]";

  grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
  absl::Status ret = boottime_api_.NotifyNodeComplete(node_config_);

  if (ret.code() == absl::StatusCode::kNotFound) {
    // Retry node register if the node is not found.
    LOG(ERROR) << "Node not found. Retrying node registration.";
    if (!(ret = RegisterSelfToApi()).ok()) {
      reactor->Finish(ToGrpcStatus(ret));
      return reactor;
    }
    ret = boottime_api_.NotifyNodeComplete(node_config_);
  }
  reactor->Finish(ToGrpcStatus(ret));
  return reactor;
}

grpc::ServerUnaryReactor* BootTimeServiceImpl::SetDuration(
    [[maybe_unused]] grpc::CallbackServerContext* context,
    const phosphor::boottime::SetDurationRequest* request,
    [[maybe_unused]] phosphor::boottime::SetDurationResponse* response) {
  LOG(INFO) << "SetDuration[" << instance_number_
            << "]: name=" << request->name()
            << ", duration=" << request->duration_ms();

  grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
  // Check request content
  if (request->name().empty() || request->name().length() > 1024) {
    reactor->Finish(grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
                                 "Invalid name length"));
    return reactor;
  }

  absl::Status ret = boottime_api_.SetNodeDuration(
      node_config_, request->name(), request->duration_ms());
  if (ret.code() == absl::StatusCode::kNotFound) {
    // Retry node register if the node is not found.
    LOG(ERROR) << "Node not found. Retrying node registration.";
    if (!(ret = RegisterSelfToApi()).ok()) {
      reactor->Finish(ToGrpcStatus(ret));
      return reactor;
    }
    ret = boottime_api_.SetNodeDuration(node_config_, request->name(),
                                        request->duration_ms());
  }
  reactor->Finish(ToGrpcStatus(ret));
  return reactor;
}

grpc::ServerUnaryReactor* BootTimeServiceImpl::GetBootTime(
    [[maybe_unused]] grpc::CallbackServerContext* context,
    [[maybe_unused]] const phosphor::boottime::GetBootTimeRequest* request,
    phosphor::boottime::GetBootTimeResponse* response) {
  LOG(INFO) << "GetBootTime[" << instance_number_ << "]";

  grpc::ServerUnaryReactor* reactor = context->DefaultReactor();
  std::vector<std::tuple<std::string, int64_t, int64_t>> checkpoints =
      boottime_api_.GetNodeCheckpointList(node_config_);
  for (const auto& [name, wall_time_ms, mono_time_ms] : checkpoints) {
    auto* rbf = response->add_reboot_flow();
    rbf->set_stage(name);
    rbf->set_timestamp_wall_ms(wall_time_ms);
    rbf->set_timestamp_mono_ms(mono_time_ms);
  }

  std::vector<std::tuple<std::string, int64_t>> durations =
      boottime_api_.GetNodeAdditionalDurations(node_config_);
  for (const auto& [name, duration_ms] : durations) {
    auto* d = response->add_durations();
    d->set_name(name);
    d->set_duration_ms(duration_ms);
  }

  response->mutable_stat()->set_is_rebooting(
      boottime_api_.IsNodeRebooting(node_config_));

  reactor->Finish(grpc::Status::OK);
  return reactor;
}

}  // namespace blobs
