#include "authz_server.h"

#include <chrono>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <format>
#include <fstream>
#include <iostream>
#include <iterator>
#include <memory>
#include <string>
#include <string_view>
#include <utility>

#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/synchronization/mutex.h"
#include "grpc/grpc_security_constants.h"
#include "grpcpp/ext/proto_server_reflection_plugin.h"
#include "grpcpp/security/auth_context.h"
#include "grpcpp/security/server_credentials.h"
#include "grpcpp/security/tls_certificate_provider.h"
#include "grpcpp/security/tls_credentials_options.h"
#include "grpcpp/server_builder.h"
#include "grpcpp/server_context.h"
#include "grpcpp/support/status.h"
#include "nlohmann/json.hpp"
#include "nlohmann/json_fwd.hpp"
#include "jwt-cpp/jwt.h"
#include "jwt-cpp/traits/nlohmann-json/defaults.h"
#include "config_parser.h"
#include "oauth_utils.h"
#include "oauth.pb.h"
#include "zatar/generate_self_signed_cert.h"
#include "bmcweb_authorizer_singleton.h"

namespace milotic::authz {
namespace {

using ::milotic::authn::GenerateRandomRsaKey;
using ::oauth::ExchangeRequest;
using ::oauth::ExchangeResponse;
using ::oauth::HiscTokenRequest;
using ::oauth::HiscTokenResponse;
using ::oauth::MintTokenRequest;
using ::oauth::MintTokenResponse;
using ::oauth::SignatureAlgorithm;
using ::oauth::TokenType;

std::shared_ptr<grpc::ServerCredentials> GetCredentials(
    const ServerConfiguration& config) {
  constexpr unsigned int kFileWatcherRefreshIntervalSec = 30;
  grpc::experimental::TlsServerCredentialsOptions options(
      std::make_shared<grpc::experimental::FileWatcherCertificateProvider>(
          config.server_key_path, config.server_certificate_path,
          config.trust_bundle_path, kFileWatcherRefreshIntervalSec));

  options.set_cert_request_type(
      GRPC_SSL_REQUEST_AND_REQUIRE_CLIENT_CERTIFICATE_AND_VERIFY);
  options.watch_identity_key_cert_pairs();
  options.watch_root_certs();
  options.set_crl_directory(config.crl_directory);

  return grpc::experimental::TlsServerCredentials(options);
}

class HiscCert {
 public:
  explicit HiscCert(uint32_t port_id, uint32_t life_time_in_seconds,
                    std::string_view public_key,
                    HiscTokenSystemDependency& hisc_token_system_dependency) {
    // save public key to /tmp/hiscXXXXXX file
    char tmpname[] = "/tmp/hiscXXXXXX";
    int fd = hisc_token_system_dependency.LibcMkstemp(tmpname);
    if (fd == -1) {
      status_ = absl::InternalError("Failed save key to tmp file");
      return;
    }
    public_key_file_name_ = tmpname;
    std::ofstream public_key_file(public_key_file_name_.c_str());
    public_key_file << public_key;
    public_key_file.close();
    close(fd);
    // sign the public key
    std::string cmd = std::format(kHiscCertGenCmd, port_id,
                                  life_time_in_seconds, public_key_file_name_);
    int ret_code =
        hisc_token_system_dependency.RunSshKeyGen(cmd, public_key_file_name_);
    LOG(INFO) << "Execute Command:\n" << cmd << "\n";
    if (ret_code != 0) {
      status_ =
          absl::InternalError(absl::StrCat("Failed execute command:\n", cmd));
      return;
    }

    cert_file_name_ = std::format("{}-cert.pub", public_key_file_name_);
    // Read the certificate
    std::ifstream cert_file(cert_file_name_);
    if (!cert_file.is_open()) {
      status_ = absl::InternalError(
          absl::StrCat("Failed opening cert file: ", cert_file_name_));
      return;
    }

    cert_.append((std::istreambuf_iterator<char>(cert_file)),
                 std::istreambuf_iterator<char>());
    cert_file.close();
    status_ = absl::OkStatus();
  }
  virtual ~HiscCert() {
    if (!public_key_file_name_.empty()) {
      std::remove(public_key_file_name_.c_str());
    }
    if (!cert_file_name_.empty()) {
      std::remove(cert_file_name_.c_str());
    }
  }
  absl::Status status_;
  std::string cert_;

 private:
  std::string public_key_file_name_;
  std::string cert_file_name_;
};

}  // namespace

namespace impl {

AuthorizationServiceImpl::AuthorizationServiceImpl(
    const ServerConfiguration& server_config)
    : authz_config_(std::make_unique<AuthzConfiguration>(
          nlohmann::json(), server_config.offline_node_entities_path,
          server_config.google_machine_identity_path)),
      token_count_(0),
      server_config_(server_config) {
  // Load Authz Config
  LoadAuthzConfig();

  // Generate Private Key
  absl::StatusOr<std::string> rsa_private_key =
      GenerateRandomRsaKey(server_config.rsa_public_key_path);
  if (!rsa_private_key.ok()) {
    LOG(ERROR) << "Failed GenerateRandomRsaKey: " << rsa_private_key.status();
    return;
  }
  rsa_private_key_ = std::move(*rsa_private_key);
}

void AuthorizationServiceImpl::LoadAuthzConfig() {
  std::ifstream authz_policy_file(server_config_.authz_configuration_path);
  if (!authz_policy_file.is_open()) {
    LOG(WARNING) << "Authz policy file at '"
                 << server_config_.authz_configuration_path << "' is missing.";
    return;
  }
  std::string authz_policy_buffer =
      std::string(std::istreambuf_iterator<char>(authz_policy_file),
                  std::istreambuf_iterator<char>());
  nlohmann::json authz_policy_json = nlohmann::json::parse(
      authz_policy_buffer, nullptr, /*allow_exceptions*/ false);
  if (authz_policy_json.is_discarded()) {
    LOG(WARNING) << "Authz policy file at '"
                 << server_config_.authz_configuration_path << "' is invalid."
                 << std::endl
                 << "|authz_policy_buffer|=" << authz_policy_buffer;
  }
  authz_config_->ReloadConfig(authz_policy_json,
                              /*platform_config=*/nlohmann::json());
}

grpc::Status AuthorizationServiceImpl::Exchange(
    grpc::ServerContext* /*context*/, const ExchangeRequest* /*request*/,
    ExchangeResponse* /*response*/) {
  return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
                      "Exchange RPC is not implemented yet");
}

grpc::Status AuthorizationServiceImpl::MintToken(
    grpc::ServerContext* context, const MintTokenRequest* request,
    MintTokenResponse* response) {
  if (GetServerFqdn().empty()) {
    LOG(WARNING) << "Server fqdn is empty";
    return grpc::Status(grpc::StatusCode::INTERNAL,
                        "Internal Server fqdn is empty.");
  }
  if (grpc::Status status = AuthorizeMintTokenRpc(*context->auth_context());
      !status.ok()) {
    LOG(WARNING) << "Peer is not authorized: " << status.error_message();
    return status;
  }
  if (grpc::Status status = CheckMintTokenRequest(*request); !status.ok()) {
    LOG(WARNING) << "Request is invalid: " << status.error_message();
    return status;
  }
  PeerSpiffeIdentity peer_identity;
  if (grpc::Status status =
          BmcWebAuthorizerSingleton::GetPeerIdentityFromAuthContext(
              *context->auth_context(), peer_identity);
      !status.ok()) {
    return status;
  }
  std::string subject = GenerateOAuthSubject(peer_identity);

  auto token_builder =
      jwt::create()
          .set_type("JWT")
          .set_issuer("BMC Local Authorization Server")
          .set_subject(subject)
          .set_audience(GetServerFqdn())
          .set_id(GetAndIncreaseTokenCount())
          .set_issued_at(std::chrono::system_clock::now())
          .set_expires_at(std::chrono::system_clock::now() +
                          std::chrono::seconds{request->valid_for().seconds()})
          .set_payload_claim("scope",
                             "Redfish.Role." + request->redfish_role());
  try {
    std::string token =
        token_builder.sign(jwt::algorithm::rs256("", rsa_private_key_));
    response->set_token(token);
  } catch (const jwt::error::signature_generation_exception& e) {
    return grpc::Status(
        grpc::StatusCode::INTERNAL,
        absl::StrCat("signature_generation_exception: ", e.what()));
  } catch (const jwt::error::rsa_exception& e) {
    return grpc::Status(grpc::StatusCode::INTERNAL,
                        absl::StrCat("rsa_exception: ", e.what()));
  } catch (...) {
    LOG(ERROR) << "Unexpected exception was caught.";
    return grpc::Status(grpc::StatusCode::INTERNAL,
                        absl::StrCat("unexpected exception was caught"));
  }
  LOG(INFO) << "Created token for " << subject << "; redfish role is "
            << request->redfish_role();
  return grpc::Status::OK;
}

grpc::Status AuthorizationServiceImpl::AuthorizeMintTokenRpc(
    const ::grpc::AuthContext& context) {
  PeerSpiffeIdentity identity;
  if (grpc::Status status =
          BmcWebAuthorizerSingleton::GetPeerIdentityFromAuthContext(context,
                                                                    identity);
      !status.ok()) {
    return status;
  }

  if (!authz_config_->IsPeerResourceOwner(identity)) {
    return grpc::Status(
        grpc::StatusCode::PERMISSION_DENIED,
        absl::StrCat("Peer is not a resource owner! |identity|=",
                     identity.DebugString()));
  }

  return grpc::Status::OK;
}

grpc::Status AuthorizationServiceImpl::CheckMintTokenRequest(
    const MintTokenRequest& request) {
  if (request.token_type() != TokenType::TOKEN_JWT) {
    return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
                        "Only TokenType::TOKEN_JWT is supported.");
  }
  if (request.alg() != SignatureAlgorithm::ALG_RS256) {
    return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
                        "Only SignatureAlgorithm::ALG_RS256 is supported.");
  }
  if (request.valid_for().nanos() != 0) {
    return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
                        "Nanos in |valid_for| is not supported.");
  }
  // 1 hour
  constexpr std::int64_t kMinimumDurationSeconds = 60 * 60;
  // 30 days
  constexpr std::int64_t kMaximumDurationSeconds = 30 * 24 * 60 * 60;

  if (request.valid_for().seconds() > kMaximumDurationSeconds ||
      request.valid_for().seconds() < kMinimumDurationSeconds) {
    return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
                        "|valid_for| must be between 1 hour and 30 days.");
  }

  if (request.has_redfish_privileges()) {
    return grpc::Status(grpc::StatusCode::UNIMPLEMENTED,
                        "Setting |RedfishPrivileges| in |redfish_scope| is "
                        "not supported yet.");
  }

  return grpc::Status::OK;
}

std::string AuthorizationServiceImpl::GetServerFqdn() {
  absl::MutexLock lock(&mutex_);
  return server_config_.server_fqdn;
}

void AuthorizationServiceImpl::SetServerFqdn(const std::string& fqdn) {
  absl::MutexLock lock(&mutex_);
  server_config_.server_fqdn = fqdn;
}

std::string AuthorizationServiceImpl::GetAndIncreaseTokenCount() {
  absl::MutexLock lock(&mutex_);
  std::size_t token_count = token_count_;
  token_count_++;
  return std::to_string(token_count);
}

grpc::Status AuthorizationServiceImpl::HiscToken(
    grpc::ServerContext* context, const HiscTokenRequest* request,
    HiscTokenResponse* response) {
  if (grpc::Status status = AuthorizeHiscTokenRpc(*context->auth_context());
      !status.ok()) {
    LOG(WARNING) << "Peer is not authorized: " << status.error_message();
    return status;
  }
  return HiscToken(request, response, bmc_hisc_token_system_dependency_);
}

grpc::Status AuthorizationServiceImpl::HiscToken(
    const HiscTokenRequest* request, HiscTokenResponse* response,
    HiscTokenSystemDependency& hisc_token_system_dependency) {
  if (request->token_lifetime_seconds() > kMaxHiscCertLifeTimeInSeconds) {
    return grpc::Status(
        grpc::StatusCode::INVALID_ARGUMENT,
        absl::StrCat("Request certificate lifetime in seconds is ",
                     request->token_lifetime_seconds(), ", longer than ",
                     kMaxHiscCertLifeTimeInSeconds));
  }
  HiscCert hisc_cert(request->hisc_port_id(), request->token_lifetime_seconds(),
                     request->public_key(), hisc_token_system_dependency);

  if (!hisc_cert.status_.ok()) {
    return grpc::Status(grpc::StatusCode::INTERNAL,
                        hisc_cert.status_.ToString());
  }

  response->set_token(hisc_cert.cert_);
  return grpc::Status::OK;
}

grpc::Status AuthorizationServiceImpl::AuthorizeHiscTokenRpc(
    const ::grpc::AuthContext& context) {
  PeerSpiffeIdentity identity;
  if (grpc::Status status =
          BmcWebAuthorizerSingleton::GetPeerIdentityFromAuthContext(context,
                                                                    identity);
      !status.ok()) {
    return status;
  }

  if (!authz_config_->IsPeerResourceOwner(identity)) {
    return grpc::Status(
        grpc::StatusCode::PERMISSION_DENIED,
        absl::StrCat("Peer is not a resource owner! |identity|=",
                     identity.DebugString()));
  }

  return grpc::Status::OK;
}

}  // namespace impl

AuthorizationServer::~AuthorizationServer() {
  if (server_ != nullptr) {
    LOG(INFO) << "Server shutting down..";
    server_->Shutdown();
  }
}

AuthorizationServer::AuthorizationServer(const ServerConfiguration& config)
    : server_config_(config) {}

void AuthorizationServer::StartServer() {
  std::string server_address(absl::StrCat("[::]:", server_config_.port));
  service_ = std::make_unique<impl::AuthorizationServiceImpl>(server_config_);
  grpc::reflection::InitProtoReflectionServerBuilderPlugin();

  grpc::ServerBuilder builder;
  builder.AddListeningPort(server_address, GetCredentials(server_config_));
  builder.RegisterService(service_.get());

  // Set up the server to start accepting requests.
  server_ = builder.BuildAndStart();
  LOG(INFO) << "Server listening on " << server_address;
}

void AuthorizationServer::ReloadAuthzConfig(const std::string& server_fqdn) {
  LOG(INFO) << "Reloading Server";
  service_->LoadAuthzConfig();
  service_->SetServerFqdn(server_fqdn);
}

void AuthorizationServer::Wait() { server_->Wait(); }

}  // namespace milotic::authz
