#include "tlbmc/redfish/query_parameters.h"

#include <cstddef>
#include <string>
#include <vector>

#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/numbers.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/strings/strip.h"
#include "boost/url/params_view.hpp"
#include "nlohmann/json.hpp"

namespace milotic_tlbmc {

std::string ExpandTypeToUrlParam(ExpandType expand_type) {
  switch (expand_type) {
    case ExpandType::kNoLinks:
      return ".";
    case ExpandType::kLinksOnly:
      return "~";
    case ExpandType::kAll:
      return "*";
    default:
      return "";
  }
}

absl::StatusOr<QueryParameters> QueryParameters::Create(
    boost::urls::params_view request_query_parameters) {
  QueryParameters query_parameters;
  if (request_query_parameters.empty()) {
    return query_parameters;
  }

  // Currently we only support one parameter
  if (request_query_parameters.size() > 1) {
    return absl::InvalidArgumentError(
        "Multiple query parameters are not supported.");
  }

  for (const boost::urls::params_view::value_type it :
       request_query_parameters) {
    if (it.key != "$expand") {
      return absl::InvalidArgumentError("Unsupported query parameter.");
    }

    // We have to parse the expand type and levels if applicable.
    // Examples: $expand=. or $expand=.($levels=2)

    // We support the following
    // expand=. (Expand with no links)
    // expand=~ (Expand only links)
    // expand=* (Expand all)
    absl::string_view param_value = it.value;
    if (absl::StartsWith(param_value, ".")) {
      query_parameters.SetExpandType(ExpandType::kNoLinks);
      param_value = absl::StripPrefix(param_value, ".");
    } else if (absl::StartsWith(param_value, "~")) {
      query_parameters.SetExpandType(ExpandType::kLinksOnly);
      param_value = absl::StripPrefix(param_value, "~");
    } else if (absl::StartsWith(param_value, "*")) {
      query_parameters.SetExpandType(ExpandType::kAll);
      param_value = absl::StripPrefix(param_value, "*");
    }

    // Expand level is defaulted to 1.
    query_parameters.SetExpandLevel(1);

    if (param_value.empty()) {
      return query_parameters;
    }

    // Get levels if exists
    if (!absl::StartsWith(param_value, "($levels=") ||
        !absl::EndsWith(param_value, ")")) {
      return absl::InvalidArgumentError(
          absl::StrFormat("Invalid Expand Syntax. Got: %s", param_value));
    }
    param_value = absl::StripPrefix(param_value, "($levels=");
    param_value = absl::StripSuffix(param_value, ")");
    int expand_level = 0;
    if (!absl::SimpleAtoi(param_value, &expand_level)) {
      return absl::InvalidArgumentError(absl::StrFormat(
          "Expand Level was not a number. Got: %s", param_value));
    }
    query_parameters.SetExpandLevel(expand_level);
  }

  return query_parameters;
}

namespace {

void GetUnexpandedUrlsHelper(const nlohmann::json& resp_json,
                             const nlohmann::json::json_pointer& cur_pointer,
                             ExpandType expand_type, bool in_links,
                             std::vector<ExpandNode>& unexpanded_urls) {
  if (resp_json.is_primitive()) {
    return;
  }
  if (resp_json.is_array()) {
    for (size_t i = 0; i < resp_json.size(); ++i) {
      GetUnexpandedUrlsHelper(resp_json[i], cur_pointer / i, expand_type,
                              in_links, unexpanded_urls);
    }
    return;
  }

  if (resp_json.is_object()) {
    // Unexpanded URLs are objects with only an @odata.id
    if (resp_json.size() == 1 && resp_json.contains("@odata.id")) {
      unexpanded_urls.push_back(ExpandNode{.json_pointer = cur_pointer,
                                           .url = resp_json["@odata.id"]});
      return;
    }

    // Otherwise recurse on object values
    for (const auto& [key, value] : resp_json.items()) {
      bool local_in_links = in_links;
      if (!local_in_links) {
        // Check if this is a links node
        local_in_links = key == "Links";
      }
      // Only traverse the parts of the tree the user asked for
      // Per section 7.3 of the redfish specification
      if (local_in_links && expand_type == ExpandType::kNoLinks) {
        continue;
      }
      if (!local_in_links && expand_type == ExpandType::kLinksOnly) {
        continue;
      }

      GetUnexpandedUrlsHelper(value, cur_pointer / key, expand_type,
                              local_in_links, unexpanded_urls);
    }
  }
}

}  // namespace

std::vector<ExpandNode> GetUnexpandedUrls(const nlohmann::json& resp,
                                          ExpandType expand_type) {
  std::vector<ExpandNode> unexpanded_urls;
  GetUnexpandedUrlsHelper(resp, nlohmann::json::json_pointer(""), expand_type,
                          false, unexpanded_urls);
  return unexpanded_urls;
}

}  // namespace milotic_tlbmc
