#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 "http_request.hpp"
#include "http_response.hpp"
#include "async_resp.hpp"
#include "nlohmann/json_fwd.hpp"
#include "tlbmc/redfish/query_parameters.h"

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
