#include "json_utils.h"

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

#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.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*>();
  }
}

template <typename ReturnType>
ReturnType* GetValueAsMutableType(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<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");
}

absl::StatusOr<nlohmann::json> CheckAndGetValueAsJson(
    const nlohmann::json& root, const nlohmann::json::json_pointer& pointer) {
  if (!root.contains(pointer)) {
    return absl::NotFoundError(
        "Could not find pointer: " + pointer.to_string() +
        " in json: " + root.dump());
  }
  return root[pointer];
}

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

nlohmann::json::array_t* GetValueAsMutableArray(nlohmann::json& root,
                                                std::string_view key) {
  return GetValueAsMutableType<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 nlohmann::json::number_unsigned_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;
  }

  const nlohmann::json::number_integer_t* int_ptr =
      GetValueAsType<nlohmann::json::number_integer_t>(root, key, "number");
  if (int_ptr != nullptr) {
    return static_cast<double>(*int_ptr);
  }

  const nlohmann::json::number_unsigned_t* unsigned_ptr =
      GetValueAsType<nlohmann::json::number_unsigned_t>(root, key, "number");
  if (unsigned_ptr != nullptr) {
    return static_cast<double>(*unsigned_ptr);
  }

  LOG(INFO) << absl::StrCat("Invalid json: Failed to convert value at ", key,
                            " to double ", root.dump());
  return std::nullopt;
}

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
