#include "tlbmc/redfish/expand_query_aggregator.h"

#include <algorithm>
#include <array>
#include <cstddef>
#include <limits>
#include <memory>
#include <string>
#include <system_error>
#include <utility>
#include <vector>

#include "absl/log/log.h"
#include "absl/strings/string_view.h"
#include "absl/strings/substitute.h"
#include "boost/url/url.hpp"  // NOLINT
#include "nlohmann/json_fwd.hpp"
#include "tlbmc/redfish/query_parameters.h"
#include "dbus_utility.hpp" // NOLINT
#include "async_resp.hpp" // NOLINT
#include "http_request.hpp" // NOLINT

namespace milotic_tlbmc {

using ::crow::Request;
using ::crow::Response;

std::string ExpandQueryAggregator::CreateExpandQueryUrl(
    absl::string_view url, [[maybe_unused]] const ExpandNode& expand_node) {
  return absl::Substitute(
      "$0?$$expand=$1($$levels=$2)", url,
      ExpandTypeToUrlParam(query_parameters_.GetExpandType()),
      std::to_string(query_parameters_.GetExpandLevel() - 1));
}

void ExpandQueryAggregator::StartQuery() {
  std::vector<ExpandNode> urls_to_expand = GetUnexpandedUrls(
      final_async_resp_->res.jsonValue, query_parameters_.GetExpandType());
  for (const ExpandNode& url_to_expand : urls_to_expand) {
    boost::urls::url expand_url(url_to_expand.url);
    boost::beast::http::request<boost::beast::http::string_body> request;
    std::string request_url =
        CreateExpandQueryUrl(expand_url.encoded_path(), url_to_expand);
    request.target(request_url);
    request.method(boost::beast::http::verb::get);

    std::error_code ec;
    Request sub_req(std::move(request), ec);
    auto sub_async_resp =
        std::make_shared<bmcweb::AsyncResp>(final_async_resp_->strand_);
    sub_async_resp->res.setCompleteRequestHandler(
        // We must extend the lifetime of the final_response to the lifetime
        // of the sub_async_resp.
        [expand_aggregator = shared_from_this(), url_to_expand](Response& res) {
          expand_aggregator->AddResponseToFinalResponse(
              url_to_expand, res);
        });
    LOG(INFO) << "Sub request: " << sub_req.target();
    smart_router_->Handle(sub_req, sub_async_resp);
  }
}

void ExpandQueryAggregator::AddResponseToFinalResponse(
    const ExpandNode& expand_node, Response& sub_response) {
  // Special handling for subresponse error
  if (sub_response.resultInt() < 200 || sub_response.resultInt() >= 400) {
    LOG(WARNING) << "Queried " << expand_node.url << " but got error code "
                 << sub_response.resultInt();
    // Determine the final error code
    final_async_resp_->res.result(
        DetermineFinalErrorCode(sub_response.resultInt()));

    // Move Error Messages to final response
    PropagateErrorMessage(sub_response.jsonValue);

    // Remove error from subresponse before moving
    auto error = sub_response.jsonValue.find("error");
    if (error != sub_response.jsonValue.end()) {
      sub_response.jsonValue.erase(error);
    }
  }

  final_async_resp_->res.jsonValue[expand_node.json_pointer] =
      std::move(sub_response.jsonValue);
}

ErrorInformation ExpandQueryAggregator::GetErrorInformation(
    const nlohmann::json& response_json) {
  ErrorInformation error_information;
  auto error = response_json.find("error");
  if (error != response_json.end()) {
    auto message = error->find("message");
    if (message != error->end()) {
      error_information.error_message = *message;
    }

    auto code = error->find("code");
    if (code != error->end()) {
      error_information.error_code = *code;
    }

    auto extended_info = error->find("@Message.ExtendedInfo");
    if (extended_info != error->end() && extended_info->is_array()) {
      error_information.extended_info = *extended_info;
    }
  }
  return error_information;
}

void ExpandQueryAggregator::PropagateErrorMessage(
    nlohmann::json& sub_response_json) {
  nlohmann::json& final_response_json_error =
      final_async_resp_->res.jsonValue["error"];

  ErrorInformation error_information = GetErrorInformation(sub_response_json);

  // If the final response doesn't have an error object, create and populate
  if (!final_response_json_error.is_object()) {
    final_response_json_error["code"] = error_information.error_code;
    final_response_json_error["message"] = error_information.error_message;
  } else {
    // Else use generic error code and message
    final_response_json_error["code"] = "Base.1.11.0.GeneralError";
    final_response_json_error["message"] =
        "A general error has occurred. See Resolution for information on how "
        "to resolve the error.";
  }

  // Populate the Extended Info
  nlohmann::json& final_extended_info =
      final_response_json_error["@Message.ExtendedInfo"];

  // Create Extended Info array if it doesn't exist
  if (!final_extended_info.is_array()) {
    final_extended_info = nlohmann::json::array();
  }

  // Populate subresponse's extended info into the final response's extended
  // info
  for (const auto& sub_response_extended_info :
       error_information.extended_info) {
    final_extended_info.push_back(sub_response_extended_info);
  }
}

// Propogates the worst error code to the final response.
// The order of error code is (from high to low)
// 500 Internal Server Error
// 511 Network Authentication Required
// 510 Not Extended
// 508 Loop Detected
// 507 Insufficient Storage
// 506 Variant Also Negotiates
// 505 HTTP Version Not Supported
// 504 Gateway Timeout
// 503 Service Unavailable
// 502 Bad Gateway
// 501 Not Implemented
// 401 Unauthorized
// 451 - 409 Error codes (not listed explictly)
// 408 Request Timeout
// 407 Proxy Authentication Required
// 406 Not Acceptable
// 405 Method Not Allowed
// 404 Not Found
// 403 Forbidden
// 402 Payment Required
// 400 Bad Request
unsigned ExpandQueryAggregator::DetermineFinalErrorCode(
    unsigned sub_response_code) {
  unsigned cur_code = final_async_resp_->res.resultInt();
  // We keep a explicit list for error codes that this project often uses
  // Higer priority codes are in lower indexes
  constexpr std::array<unsigned, 13> ordered_codes = {
      500, 507, 503, 502, 501, 401, 412, 409, 406, 405, 404, 403, 400};
  size_t final_code_index = std::numeric_limits<size_t>::max();
  size_t sub_response_code_index = std::numeric_limits<size_t>::max();
  for (size_t i = 0; i < ordered_codes.size(); ++i) {
    if (ordered_codes[i] == cur_code) {
      final_code_index = i;
    }
    if (ordered_codes[i] == sub_response_code) {
      sub_response_code_index = i;
    }
  }
  if (final_code_index != std::numeric_limits<size_t>::max() &&
      sub_response_code_index != std::numeric_limits<size_t>::max()) {
    return final_code_index <= sub_response_code_index ? cur_code
                                                       : sub_response_code;
  }
  if (sub_response_code == 500 || cur_code == 500) {
    return 500;
  }
  if (sub_response_code > 500 || cur_code > 500) {
    return std::max(cur_code, sub_response_code);
  }
  if (sub_response_code == 401) {
    return sub_response_code;
  }
  return std::max(cur_code, sub_response_code);
}

}  // namespace milotic_tlbmc
