// Copyright 2026 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "utils/distinguished_name.h"

#include <cstddef>
#include <string>
#include <utility>

#include "absl/container/flat_hash_map.h"
#include "absl/status/status.h"
#include "absl/status/status_macros.h"
#include "absl/status/statusor.h"
#include "absl/strings/ascii.h"
#include "absl/strings/escaping.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"

namespace credentio {
namespace {

// Consumes an OID.
//
// oid = 1*DIGIT *("." 1*DIGIT)
// (but we only enforce that it starts with a digit and contains digits and ".")
absl::StatusOr<std::string> ConsumeOid(absl::string_view* s) {
  if (s->empty() || !absl::ascii_isdigit(s->front())) {
    return absl::InvalidArgumentError("expected OID value starting with digit");
  }
  size_t len = s->find_first_not_of("0123456789.");
  std::string oid = std::string(s->substr(0, len));
  s->remove_prefix(oid.size());
  return oid;
}

// Consumes an attribute type (e.g., "CN" or "1.2.3").
//
// attributeType = (ALPHA 1*keychar) / oid
// keychar    = ALPHA / DIGIT / "-"
absl::StatusOr<std::string> ConsumeAttr(absl::string_view* s) {
  if (s->empty()) {
    return absl::InvalidArgumentError("empty attribute name");
  }
  if (absl::ascii_isdigit(s->front())) {
    return ConsumeOid(s);
  }
  if (!absl::ascii_isalpha(s->front())) {
    return absl::InvalidArgumentError(
        "expected attribute name starting with alpha");
  }
  std::string value;
  while (!s->empty()) {
    if (absl::ascii_isalpha(s->front()) || absl::ascii_isdigit(s->front()) ||
        s->front() == '-') {
      value.push_back(s->front());
      s->remove_prefix(1);
    } else {
      break;
    }
  }
  return value;
}

// Consumes a #aabbccddee string, returning decoded value.
absl::StatusOr<std::string> ConsumeHexStringValue(absl::string_view* s) {
  absl::string_view temp = *s;
  if (!absl::ConsumePrefix(&temp, "#")) {
    return absl::InvalidArgumentError("expected hex string starting with #");
  }

  absl::string_view digits =
      temp.substr(0, temp.find_first_not_of("0123456789abcdefABCDEF"));
  temp.remove_prefix(digits.length());
  std::string value;
  if (!absl::HexStringToBytes(digits, &value)) {
    return absl::InvalidArgumentError("cannot parse hex string");
  }
  *s = temp;
  return value;
}

// Consumes a backslash escape, returning decoded character.
//
// pair       = "\" ( special / "\" / QUOTATION / hexpair )
// stringchar = <any character except one of special, "\" or QUOTATION >
//
// hexstring  = 1*hexpair
// hexpair    = hexchar hexchar
//
// hexchar    = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
//              / "a" / "b" / "c" / "d" / "e" / "f"
// special    = "," / "=" / "+" / "<" /  ">" / "#" / ";"
absl::StatusOr<std::string> ConsumeBackslashEscape(absl::string_view* s) {
  absl::string_view temp = *s;
  if (!absl::ConsumePrefix(&temp, "\\")) {
    return absl::InvalidArgumentError(
        "expected backslash escape starting with \\");
  }
  if (temp.empty()) {
    return absl::InvalidArgumentError("backslash at end of input");
  }
  if (absl::ascii_isxdigit(absl::ascii_toupper(temp.front()))) {
    std::string decoded_hex;
    if (temp.length() < 2 ||
        !absl::HexStringToBytes(temp.substr(0, 2), &decoded_hex)) {
      return absl::InvalidArgumentError("cannot decode hex backslash escape");
    }
    temp.remove_prefix(2);
    *s = temp;
    return decoded_hex;
  }
  if (!absl::StrContains(",=+<>#;\"\\", temp.front())) {
    return absl::InvalidArgumentError("invalid backslash escape");
  }
  std::string value = std::string(temp.substr(0, 1));
  temp.remove_prefix(1);
  *s = temp;
  return value;
}

// Consumes a double-quoted string, returning decoded value.
// string     = ... / QUOTATION *( quotechar / pair ) QUOTATION ; only from v2
// quotechar     = <any character except "\" or QUOTATION >
absl::StatusOr<std::string> ConsumeQuotedStringValue(absl::string_view* s) {
  absl::string_view temp = *s;
  if (!absl::ConsumePrefix(&temp, "\"")) {
    return absl::InvalidArgumentError(
        "expected quoted string starting with \"");
  }
  std::string value;
  while (!temp.empty()) {
    if (absl::ConsumePrefix(&temp, "\"")) {
      *s = temp;
      return value;
    }
    if (temp.front() == '\\') {
      ABSL_ASSIGN_OR_RETURN(auto unescaped, ConsumeBackslashEscape(&temp));
      absl::StrAppend(&value, unescaped);
    } else {
      value.push_back(temp.front());
      temp.remove_prefix(1);
    }
  }
  return absl::InvalidArgumentError("closing '\"' not found");
}

// Consumes an attribute value and returns the decoded value.
//
// attributeValue = string
// string     = *( stringchar / pair )
//              / "#" hexstring
//              / QUOTATION *( quotechar / pair ) QUOTATION ; only from v2
absl::StatusOr<std::string> ConsumeValue(absl::string_view* s) {
  if (!s->empty() && s->front() == '#') {
    return ConsumeHexStringValue(s);
  }
  if (!s->empty() && s->front() == '"') {
    return ConsumeQuotedStringValue(s);
  }
  absl::string_view temp = *s;
  std::string value;
  while (!temp.empty() && !absl::StrContains(",=+<>#;\"", temp.front())) {
    if (temp.front() == '\\') {
      ABSL_ASSIGN_OR_RETURN(auto unescaped, ConsumeBackslashEscape(&temp));
      absl::StrAppend(&value, unescaped);
    } else {
      value.push_back(temp.front());
      temp.remove_prefix(1);
    }
  }
  *s = temp;
  return value;
}

// Consumes an attribute/value (e.g., "FOO=Bar") and returns the pair.
absl::StatusOr<std::pair<std::string, std::string>> ConsumeAttrAndValue(
    absl::string_view* s) {
  absl::string_view temp = *s;
  ABSL_ASSIGN_OR_RETURN(auto attr, ConsumeAttr(&temp));
  if (!absl::ConsumePrefix(&temp, "=")) {
    return absl::InvalidArgumentError("expected '=' after attribute name");
  }
  ABSL_ASSIGN_OR_RETURN(auto value, ConsumeValue(&temp));
  *s = temp;
  return std::make_pair(attr, value);
}

}  // namespace

absl::StatusOr<absl::flat_hash_map<std::string, std::string>>
ParseDistinguishedName(absl::string_view distinguished_name) {
  absl::flat_hash_map<std::string, std::string> attrs;
  while (!distinguished_name.empty()) {
    auto attr_and_value = ConsumeAttrAndValue(&distinguished_name);
    if (!attr_and_value.ok()) {
      return absl::Status(attr_and_value.status().code(),
                          absl::StrCat("cannot parse RFC2253 DN: ",
                                       attr_and_value.status().message()));
    }
    const auto& [attr, value] = *attr_and_value;
    for (const auto& [existing_attr, _] : attrs) {
      if (absl::EqualsIgnoreCase(existing_attr, attr)) {
        return absl::InvalidArgumentError("Duplicate attribute in RFC2253 DN");
      }
    }
    attrs[attr] = value;
    if (distinguished_name.empty()) {
      break;
    }
    if (absl::ConsumePrefix(&distinguished_name, "+")) {
      return absl::UnimplementedError("multi-valued RDN not supported");
    }
    if (!absl::ConsumePrefix(&distinguished_name, ",")) {
      return absl::InvalidArgumentError("Cannot parse RFC2253 DN");
    }
  }
  return attrs;
}

}  // namespace credentio
