// 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.
//

// A Uuid is an identifier, that is unique over all space and time.  The default
// implementation is based on UUID (DCE version), which uses the Ethernet MAC
// address of the machine, and a timestamp (which we replace with a sequence
// number).
//
//   http://en.wikipedia.org/wiki/Universally_unique_identifier
//   http://tools.ietf.org/html/rfc4122.html
//
// The reason to use DCE is that it is based on the physical
// address, which may aid debugging.

#ifndef THIRD_PARTY_CREDENTIO_UUID_UUID_H_
#define THIRD_PARTY_CREDENTIO_UUID_UUID_H_

#include <cstdint>
#include <ostream>
#include <string>

#include "absl/log/check.h"
#include "absl/numeric/int128.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"

namespace credentio {

// Uuid is the type of unique identifiers.
class Uuid {
 public:
  // In addition to the following constructors, the default copy constructor and
  // assignment operator are also allowed.
  // Uuids are not POD, because the default constructor initializes them to
  // kInvalid. However, the Google Style Guide allows static Uuid constants
  // because Uuid constructors are all constexpr, and the type has no
  // destructors.
  constexpr Uuid() : high_(0), low_(InvalidMinLo()) {}  // equal to kInvalid
  explicit constexpr Uuid(uint64_t low) : high_(0), low_(low) {}
  constexpr Uuid(uint64_t high, uint64_t low) : high_(high), low_(low) {}
  constexpr explicit Uuid(absl::uint128 raw)
      : Uuid(absl::Uint128High64(raw), absl::Uint128Low64(raw)) {}

  bool IsValid() const;

  // Conversion to/from the ASCII form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx. The
  // format uses the following ABNF, where each numerical component is
  // represented in hex, with leading zeros (although the FromString variants
  // will accept input without leading zeros). The 'x's above show the maximum
  // length of each of those components.
  //
  //   UUID = time-low "-" time-mid "-" time-high-and-version "-"
  //   clock-seq-and-reserved clock-seq-low "-" node
  //
  // FromString returns INVALID_ARGUMENT, and FromStringOrDie CHECK-fails if
  // there is a syntax error.
  std::string ToString() const;
  static absl::StatusOr<Uuid> FromString(absl::string_view s);
  static constexpr Uuid FromStringOrDie(absl::string_view s) {
    Uuid uuid;
    CHECK(Uuid::ParseFromString(s, &uuid))
        << "Syntax error: string '" << s << "' is not a Uuid";
    return uuid;
  }

  absl::uint128 ToRawNumber() const { return absl::MakeUint128(high_, low_); }
  uint64_t high64() const { return high_; }
  uint64_t low64() const { return low_; }

  // Conversion to/from 16-byte binary strings.  Layout and byte order
  // are specified by RFC 4122.
  std::string ToProtoBytes() const;
  void ToProtoBytes(std::string* s) const;

  // Convert proto string to Uuid. Returns INVALID_ARGUMENT if the Uuid could
  // not be parsed correctly.
  static absl::StatusOr<Uuid> FromProtoBytes(absl::string_view bytes);

  // Canonical Uuids
  static const Uuid kInvalid;  // Represents errors.
  static constexpr absl::string_view kInvalidRepr =
      "Uid::kInvalid";  // String representation of kInvalid.

  // We reserve 999 in invalid Uuids (in addition to kInvalid) that can be
  // used as special sentinel values that will be different from any id returned
  // by a Uuid generator. Magic values can be declared as static compile-time
  // constants.
  template <uint64_t k>
  static constexpr Uuid Magic() {
    static_assert(k < ValidMinLo(), "Argument too large");
    static_assert(k > InvalidMinLo(), "Argument too small");
    return Uuid(k);
  }
  bool IsMagic() const;

  // Range of valid Uuids
  static const Uuid kValidMin;
  static const Uuid kValidMax;

  template <typename H>
  friend H AbslHashValue(H h, const Uuid& uuid) {
    return H::combine(std::move(h), uuid.high_, uuid.low_);
  }

 private:
  // Underlying parsing function for ASCII form conversions.
  static constexpr bool ParseFromString(absl::string_view s, Uuid* uuid) {
    auto consume_hex = [](int max_chars, absl::string_view* input,
                          uint64_t* res) {
      *res = 0;
      int count = 0;
      while (count < max_chars && !input->empty()) {
        char c = input->front();
        uint32_t v = 0;
        if (c >= '0' && c <= '9') {
          v = c - '0';
        } else if (c >= 'a' && c <= 'f') {
          v = c - 'a' + 10;
        } else if (c >= 'A' && c <= 'F') {
          v = c - 'A' + 10;
        } else {
          break;
        }
        *res = (*res << 4) + v;
        input->remove_prefix(1);
        ++count;
      }
      return count > 0;
    };
    auto consume_char = [](char check_char, absl::string_view* input) {
      if (input->empty() || input->front() != check_char) return false;
      input->remove_prefix(1);
      return true;
    };

    if (s == kInvalidRepr) {
      // Equal to kInvalid (canonical value cannot be used here due to constexpr
      // restrictions).
      *uuid = Uuid();
      return true;
    }

    absl::string_view input(s);
    uint64_t time_low = 0, time_mid = 0, time_high = 0, sequence = 0, node = 0;
    bool valid = true;
    valid &= consume_hex(8, &input, &time_low);
    valid &= consume_char('-', &input);
    valid &= consume_hex(4, &input, &time_mid);
    valid &= consume_char('-', &input);
    valid &= consume_hex(4, &input, &time_high);
    valid &= consume_char('-', &input);
    valid &= consume_hex(4, &input, &sequence);
    valid &= consume_char('-', &input);
    valid &= consume_hex(12, &input, &node);
    valid &= input.empty();

    if (!valid) {
      return false;
    }

    const uint64_t high64 =
        ((node & 0xffffffffffffULL) << 16) | (sequence & 0xffffULL);
    const uint64_t low64 = ((time_high & 0xffffULL) << 48) |
                           ((time_mid & 0xffffULL) << 32) |
                           (time_low & 0xffffffffULL);
    *uuid = Uuid(high64, low64);
    return true;
  }

  // We reserve the node 00:00:00:00:00:00, time [0, 999] for invalid
  // Uuids (constants)
  static constexpr uint64_t ValidMinLo() { return 1000; }
  static constexpr uint64_t InvalidMinLo() { return 0; }

  uint64_t high_{0};
  uint64_t low_{0};
};

// Comparison operators.
inline bool operator==(Uuid a, Uuid b) {
  return a.high64() == b.high64() && a.low64() == b.low64();
}
inline bool operator!=(Uuid a, Uuid b) { return !(a == b); }
inline bool operator<(Uuid a, Uuid b) {
  return a.high64() < b.high64() ||
         (a.high64() == b.high64() && a.low64() < b.low64());
}
inline bool operator<=(Uuid a, Uuid b) {
  return a.high64() < b.high64() ||
         (a.high64() == b.high64() && a.low64() <= b.low64());
}

// Formatting.
inline std::ostream& operator<<(std::ostream& o, Uuid id) {
  return o << id.ToString();
}

class UuidGenerator {
 public:
  virtual ~UuidGenerator() = default;
  virtual Uuid Generate() const = 0;
  // Generates a V4 UUID as documented in
  // https://tools.ietf.org/html/rfc4122#section-4.4
  static const UuidGenerator& Default();
};

}  // namespace credentio

#endif  // THIRD_PARTY_CREDENTIO_UUID_UUID_H_
