#include "oauth_utils.h"

#include <exception>
#include <fstream>
#include <iterator>
#include <optional>
#include <string>
#include <string_view>

#include "absl/log/log.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "redfish_v1.pb.h"
#include "zatar/x509_certificate.h"
#include "grpcpp/support/status.h"
#include "nlohmann/json.hpp"
#include "jwt-cpp/jwt.h"
#include "jwt-cpp/traits/nlohmann-json/defaults.h"
#include "config_parser.h"

namespace milotic::authz {

std::string GenerateOAuthSubject(const PeerSpiffeIdentity& peer_identity) {
  std::string subject;

  absl::StrAppend(&subject, "URI:", peer_identity.spiffe_id);
  if (peer_identity.fqdn) {
    absl::StrAppend(&subject, ", ", "DNS:", *peer_identity.fqdn);
  }

  return subject;
}

std::string GetSubject(const std::string& certificate_path) {
  std::ifstream file(certificate_path.c_str());
  if (!file.is_open()) {
    LOG(WARNING) << "Certificate file at '" << certificate_path
                 << "' is missing.";
    return "";
  }
  std::string buffer = {std::istreambuf_iterator<char>(file),
                        std::istreambuf_iterator<char>()};

  using ::ecclesia::GetSubjectAltName;
  using ::ecclesia::SubjectAltName;
  using ::milotic::authz::GenerateOAuthSubject;
  using ::milotic::authz::PeerSpiffeIdentity;
  auto san = GetSubjectAltName(buffer);
  if (!san.ok() || !san->spiffe_id.has_value() || !san->fqdn.has_value()) {
    LOG(WARNING) << "Certificate file at '" << certificate_path
                 << "' is illegal.";
    LOG(WARNING) << "SAN is '" << san->DebugInfo();
    return "";
  }
  PeerSpiffeIdentity identity = {
      .spiffe_id = *san->spiffe_id,
      .fqdn = *san->fqdn,
  };
  return GenerateOAuthSubject(identity);
}

std::optional<std::string> GetOAuthTokenFromRequest(
    const ::redfish::v1::Request& request) {
  // Both field name of the Authorization header and the token type are case
  // insensitive
  // References
  // https://www.rfc-editor.org/rfc/rfc7230#section-3.2
  // https://www.rfc-editor.org/rfc/rfc6749#section-5.1
  for (const auto& [key, value] : request.headers()) {
    constexpr std::string_view kBearer = "Bearer ";
    if (absl::EqualsIgnoreCase(key, "Authorization") &&
        absl::StartsWithIgnoreCase(value, kBearer)) {
      return value.substr(kBearer.size());
    }
  }
  return std::nullopt;
}

grpc::Status VerifyAndExtractRoleFromToken(const std::string& token,
                                           const std::string& public_key,
                                           const std::string& expected_subject,
                                           const std::string& expected_audience,
                                           const std::string& expected_issuer,
                                           std::string& redfish_role) {
  try {
    auto verifier = jwt::verify()
                        .allow_algorithm(jwt::algorithm::rs256(public_key))
                        .with_subject(expected_subject)
                        .with_audience(expected_audience)
                        .with_issuer(expected_issuer);
    auto decoded = jwt::decode(token);
    verifier.verify(decoded);

    nlohmann::json scope = decoded.get_payload_claim("scope").to_json();
    const std::string* scope_str = scope.get_ptr<const std::string*>();
    if (scope_str == nullptr) {
      return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
                          "scope is not a string");
    }
    constexpr std::string_view kRedfishRole = "Redfish.Role.";
    if (!absl::StartsWith(*scope_str, kRedfishRole)) {
      return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
                          "scope doesn't start with \"Redfish.Role.\"");
    }
    redfish_role = scope_str->substr(kRedfishRole.size());
    return grpc::Status::OK;
  } catch (const std::exception& e) {
    // TODO(nanzhou) enumerate all the possible expceptions in jwt-cpp
    LOG(WARNING) << "Token verification failed!";
    LOG(WARNING) << "Token is " << token;
    LOG(WARNING) << "Public key is " << public_key;
    LOG(WARNING) << "Expected subject is " << expected_subject
                 << "; Expected audience is " << expected_audience
                 << "; Expected issuer is " << expected_issuer;
    return grpc::Status(grpc::StatusCode::INTERNAL, e.what());
  }
}

}  // namespace milotic::authz
