// 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 "bmc/auth.h"
#include <gmi/machine_identity.pb.h>
#include <gpowerd_build_config.h>

#include <grpcpp/grpcpp.h>
#include <string>
#include <string_view>
#include <filesystem>  // NOLINT
#include "bmc/gmi_reader.h"
#include "grpcpp/security/server_credentials.h"
#include "grpcpp/security/tls_certificate_provider.h"
#include "grpcpp/security/tls_certificate_verifier.h"
#include "grpcpp/security/tls_credentials_options.h"
#include "grpcpp/ext/proto_server_reflection_plugin.h"
#include "grpcpp/health_check_service_interface.h"
#include "absl/base/log_severity.h"
#include "absl/log/log.h"
#include "absl/strings/str_format.h"
#include "absl/status/statusor.h"
#include "zatar/generate_self_signed_cert.h"

#include "bmc/auth_loas3.h"

namespace auth {

using ::grpc::experimental::TlsCustomVerificationCheckRequest;
using ::grpc::experimental::ExternalCertificateVerifier;
using ::grpc::ServerBuilder;
using ::grpc::experimental::FileWatcherCertificateProvider;
using ::grpc::experimental::TlsServerCredentials;
using ::grpc::experimental::TlsServerCredentialsOptions;
using ::grpc::experimental::AuthorizationPolicyProviderInterface;
using ::milotic::authn::SelfSignedCertOptions;
using ::grpc::experimental::FileWatcherAuthorizationPolicyProvider;


absl::StatusOr<std::shared_ptr<grpc::ServerCredentials>> GetCredsInfo()
{
  #ifdef LOAS3_AUTH
  SetupLoas3();
  #else
  LOG(WARNING) << "LOAS3 is not enabled";
  #endif

  std::error_code file_error;
  bool file_exist = std::filesystem::exists(kZatarCertFilePath, file_error);
  if (file_error)
  {
    return absl::NotFoundError("tls file path error: " + file_error.message() +
                              "file path: "+ std::string(kZatarCertFilePath));
  }
  std::string keypair_path;
  if (file_exist)
  {
    keypair_path = std::string(kZatarCertFilePath);
  } else {
  // cert is not present (self sign a cert)
    keypair_path = absl::StrFormat("/tmp/gpowerd_self_signed_%d.pem", getpid());
    absl::StatusOr<std::string> host_name = gmi_reader::ReadGmiHostName();;
    {
      absl::Status errStatus = host_name.status();
      return absl::NotFoundError("unable to read gmi host name: " +
                                  std::string(errStatus.message()));
    }
    SelfSignedCertOptions option;
    option.server_fqdn = *host_name;
    if (absl::Status status =
            GenerateSelfSignedCertAndDump(keypair_path, option);
        !status.ok())
    {
       return absl::UnavailableError("unable to write self signed cert: " +
                                  std::string(status.message()));
    }
  }
  auto certificateProvider = std::make_shared<FileWatcherCertificateProvider>(
        keypair_path, keypair_path, std::string(kTrustBundleFilePath),
      /* refresh_interval_sec */ 30);

  TlsServerCredentialsOptions options(certificateProvider);
  options.watch_root_certs();
  options.set_root_cert_name("Zatar");
  options.watch_identity_key_cert_pairs();
  options.set_cert_request_type(
      GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
  #ifdef LOAS3_AUTH
  auto cert_verifier = ExternalCertificateVerifier::Create<PeerVerifier>();
  options.set_certificate_verifier(std::move(cert_verifier));
  #endif
  std::shared_ptr<grpc::ServerCredentials> tlsServerCredentials =
    TlsServerCredentials(options);
  if (tlsServerCredentials == nullptr)
  {
     LOG(ERROR) << "tls Server Credentials error:";
    return absl::NotFoundError("tls Server Credentials error");
  }
  return tlsServerCredentials;
}

absl::StatusOr<std::shared_ptr<AuthorizationPolicyProviderInterface>>
  GetAuthPolicy()
{
    grpc::Status policy_status;
    std::shared_ptr<AuthorizationPolicyProviderInterface> policy =
        FileWatcherAuthorizationPolicyProvider::Create(
            std::string(kGpowerDCertAuthZPolicy),
            /* policy refresh_interval_sec = 30 */ 30, &policy_status);
    if (!policy_status.ok())
    {
      return absl::NotFoundError("failed to load policy file error: " +
                                policy_status.error_message() +
                                "file path:" +
                                std::string(kGpowerDCertAuthZPolicy));
    }
    return policy;
}

}  // namespace auth

