#include "json_utils.h"

#include <cstddef>
#include <cstdint>
#include <optional>
#include <string>
#include <string_view>

#include "absl/log/log.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_cat.h"
#include "nlohmann/json.hpp"

namespace milotic::authz {
namespace {

template <typename ReturnType>
const ReturnType* GetValueAsType(const nlohmann::json& root,
                                 std::string_view key,
                                 [[maybe_unused]] std::string_view type_name) {
  if (root.is_discarded()) {
    LOG(WARNING) << "Invalid JSON object";
    return nullptr;
  }
  auto it = root.find(key);
  if (it == root.end()) {
    return nullptr;
  }
  if constexpr (std::is_same_v<ReturnType, nlohmann::json>) {
    return &(*it);
  } else {
    return it->get_ptr<const ReturnType*>();
  }
}
}  // namespace

const std::string* GetValueAsString(const nlohmann::json& root,
                                    std::string_view key) {
  return GetValueAsType<std::string>(root, key, "string");
}

const std::string* GetValueAsString(
    const nlohmann::json& root, const nlohmann::json::json_pointer& pointer) {
  if (!root.contains(pointer)) {
    return nullptr;
  }

  return root[pointer].get_ptr<const std::string*>();
}

const nlohmann::json* GetValueAsJson(const nlohmann::json& root,
                                     std::string_view key) {
  return GetValueAsType<nlohmann::json>(root, key, "object");
}

const nlohmann::json::array_t* GetValueAsArray(const nlohmann::json& root,
                                               std::string_view key) {
  return GetValueAsType<nlohmann::json::array_t>(root, key, "array");
}

const double* GetValueAsDouble(const nlohmann::json& root,
                               std::string_view key) {
  return GetValueAsType<nlohmann::json::number_float_t>(root, key, "number");
}

const int64_t* GetValueAsInt(const nlohmann::json& root, std::string_view key) {
  return GetValueAsType<nlohmann::json::number_integer_t>(root, key, "number");
}

const bool* GetValueAsBool(const nlohmann::json& root, std::string_view key) {
  return GetValueAsType<nlohmann::json::boolean_t>(root, key, "boolean");
}

const uint64_t* GetValueAsUint(const nlohmann::json& root,
                               std::string_view key) {
  return GetValueAsType<nlohmann::json::number_unsigned_t>(root, key, "number");
}

// The following functions are used to parse from json where the type may vary
// and conversion is accepted. Return a value directly since a pointer cannot be
// made to the temporary value after being converted to desired type.

std::optional<uint64_t> GetValueAsUintFromStringOrInteger(
    const nlohmann::json& root, std::string_view key) {
  const uint64_t* unsigned_ptr =
      GetValueAsType<nlohmann::json::number_unsigned_t>(root, key, "number");
  if (unsigned_ptr != nullptr) {
    return *unsigned_ptr;
  }

  const std::string* string_ptr =
      GetValueAsType<std::string>(root, key, "string");
  if (string_ptr == nullptr) {
    LOG(INFO) << absl::StrCat("Invalid json: ", key, " field does not exist ",
                              root.dump());
    return std::nullopt;
  }

  uint64_t unsigned_value;
  bool result;
  result = absl::SimpleAtoi(*string_ptr, &unsigned_value);
  if (!result) {
    LOG(INFO) << absl::StrCat("Invalid json: Failed to convert value at ", key,
                              " to unsigned value: ", root.dump());
    return std::nullopt;
  }
  LOG(INFO) << "Successfully converted string to unsigned value: "
            << unsigned_value;
  return unsigned_value;
}

std::optional<double> GetValueAsDoubleFromFloatOrInteger(
    const nlohmann::json& root, std::string_view key) {
  const double* double_ptr =
      GetValueAsType<nlohmann::json::number_float_t>(root, key, "number");
  if (double_ptr != nullptr) {
    return *double_ptr;
  }

  double double_value;
  const uint64_t* unsigned_ptr = GetValueAsType<uint64_t>(root, key, "number");
  if (unsigned_ptr == nullptr) {
    LOG(INFO) << absl::StrCat("Invalid json: Failed to convert value at ", key,
                              " to double ", root.dump());
    return std::nullopt;
  }

  double_value = static_cast<double>(*unsigned_ptr);
  LOG(INFO) << "Successfully converted integer to unsigned value: "
            << double_value;
  return double_value;
}

const std::string* GetValueAsStringFromArray(
    const nlohmann::json::array_t& array, std::size_t index) {
  if (index >= array.size()) {
    LOG(INFO) << absl::StrCat("Invalid index: Index ", index,
                              " is out of range for array of size ",
                              array.size());
    return nullptr;
  }
  return array[index].get_ptr<const std::string*>();
}

}  // namespace milotic::authz
