#include "routing.hpp"

#include <array>
#include <cerrno>
#include <cstddef>
#include <cstdint>
#include <cstdlib>
#include <memory>
#include <optional>
#include <stdexcept>
#include <string>
#include <string_view>
#include <tuple>
#include <utility>
#include <vector>

#include "absl/log/log.h"  // NOLINT(misc-include-cleaner)
#include "boost/beast/ssl/ssl_stream.hpp"  // NOLINT
#include "authorizer_enums.h"
#include "bmcweb_config.h"  // NOLINT(misc-include-cleaner)
#include "common.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "logging.hpp"
#include "utility.hpp"
#include "verb.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "error_messages.hpp"
#include "privileges.hpp"
#include "dbus_utils.hpp"
#include "grpcpp/support/status.h"  // NOLINT(misc-include-cleaner)
#include "bmcweb_authorizer_singleton.h"  // NOLINT(misc-include-cleaner)
#include "sdbusplus/unpack_properties.hpp"

namespace crow {

bool Router::isUserPrivileged(
    Request& req, const std::shared_ptr<bmcweb::AsyncResp>& asyncResp,
    BaseRule& rule, const dbus::utility::DBusPropertiesMap& userInfoMap) {
  std::string user_role{};
  const std::string* user_role_ptr = nullptr;
  const bool* remote_user = nullptr;
  const bool* password_expired = nullptr;

  const bool success = sdbusplus::unpackPropertiesNoThrow(
      redfish::dbus_utils::UnpackErrorPrinter(), userInfoMap, "UserPrivilege",
      user_role_ptr, "RemoteUser", remote_user, "UserPasswordExpired",
      password_expired);

  if (!success) {
    asyncResp->res.result(boost::beast::http::status::internal_server_error);
    return false;
  }

  if (user_role_ptr != nullptr) {
    user_role = *user_role_ptr;
    BMCWEB_LOG_DEBUG << "userName = " << req.session->username
                     << " user_role = " << *user_role_ptr;
  }

  if (remote_user == nullptr) {
    BMCWEB_LOG_ERROR << "RemoteUser property missing or wrong type";
    asyncResp->res.result(boost::beast::http::status::internal_server_error);
    return false;
  }
  bool expired = false;
  if (password_expired == nullptr) {
    if (!*remote_user) {
      BMCWEB_LOG_ERROR << "UserPasswordExpired property is expected for"
                          " local user but is missing or wrong type";
      asyncResp->res.result(boost::beast::http::status::internal_server_error);
      return false;
    }
  } else {
    expired = *password_expired;
  }

  // Get the user's privileges from the role
  redfish::Privileges user_privileges = redfish::getUserPrivileges(user_role);

  // Set isConfigureSelfOnly based on D-Bus results.  This
  // ignores the results from both pamAuthenticateUser and the
  // value from any previous use of this session.
  req.session->isConfigureSelfOnly = expired;

  // Modify privileges if isConfigureSelfOnly.
  if (req.session->isConfigureSelfOnly) {
    // Remove all privileges except ConfigureSelf
    user_privileges =
        user_privileges.intersection(redfish::Privileges{"ConfigureSelf"});
    BMCWEB_LOG_DEBUG << "Operation limited to ConfigureSelf";
  }

  if (!rule.checkPrivileges(user_privileges)) {
    asyncResp->res.result(boost::beast::http::status::forbidden);
    return false;
  }

  req.userRole = user_role;

  return true;
}

void Trie::optimizeNode(Node* node) {
  for (size_t x : node->paramChildrens) {
    if (x == 0U) {
      continue;
    }
    Node* child = &nodes[x];
    optimizeNode(child);
  }
  if (node->children.empty()) {
    return;
  }
  bool merge_with_child = true;
  for (const Node::ChildMap::value_type& kv : node->children) {
    Node* child = &nodes[kv.second];
    if (!child->isSimpleNode()) {
      merge_with_child = false;
      break;
    }
  }
  if (merge_with_child) {
    Node::ChildMap merged;
    for (const Node::ChildMap::value_type& kv : node->children) {
      Node* child = &nodes[kv.second];
      for (const Node::ChildMap::value_type& child_kv : child->children) {
        merged[kv.first + child_kv.first] = child_kv.second;
      }
    }
    node->children = std::move(merged);
    optimizeNode(node);
  } else {
    for (const Node::ChildMap::value_type& kv : node->children) {
      Node* child = &nodes[kv.second];
      optimizeNode(child);
    }
  }
}

void Trie::findRouteIndexes(const std::string& reqUrl,
                            std::vector<unsigned>& routeIndexes,
                            const Node* node, unsigned pos) const {
  if (node == nullptr) {
    node = head();
  }
  for (const Node::ChildMap::value_type& kv : node->children) {
    const std::string& fragment = kv.first;
    //  NO_CDC: to be improved later.
    const Node* child = &nodes[kv.second];
    if (pos >= reqUrl.size()) {
      if (child->ruleIndex != 0 && fragment != "/") {
        routeIndexes.push_back(child->ruleIndex);
      }
      findRouteIndexes(reqUrl, routeIndexes, child,
                       static_cast<unsigned>(pos + fragment.size()));
    } else {
      if (reqUrl.compare(pos, fragment.size(), fragment) == 0) {
        findRouteIndexes(reqUrl, routeIndexes, child,
                         static_cast<unsigned>(pos + fragment.size()));
      }
    }
  }
}

std::pair<unsigned int, RoutingParams> Trie::find(std::string_view reqUrl,
                                                  const Node* node, size_t pos,
                                                  RoutingParams* params) const {
  RoutingParams empty;
  if (params == nullptr) {
    params = &empty;
  }

  unsigned found{};
  RoutingParams match_params;

  if (node == nullptr) {
    node = head();
  }
  if (pos == reqUrl.size()) {
    return {node->ruleIndex, *params};
  }

  auto update_found = [&found,
                       &match_params](std::pair<unsigned, RoutingParams>& ret) {
    // Current Logic is to choose the rule with the lowest index in the allRules
    // vector
    bool replaceFound = found == 0U || found > ret.first;

    // With plugins enabled, we will return the first matched
    // found instead. This results in matching fixed URI segments whenever
    // possible relative to wildcards.
#if defined(PLATFORM_PLUGINS_ENABLED) ||      \
    defined(GOOGLE_COMMON_PLUGINS_ENABLED) || \
    defined(GOOGLE_PLUGINS_INTERNAL_ENABLED)
    replaceFound = found == 0U;
#endif

    if (ret.first != 0U && replaceFound) {
      found = ret.first;
      match_params = std::move(ret.second);
    }
  };

  for (const Node::ChildMap::value_type& kv : node->children) {
    const std::string& fragment = kv.first;
    const Node* child = &nodes[kv.second];

    if (reqUrl.compare(pos, fragment.size(), fragment) == 0) {
      std::pair<unsigned, RoutingParams> ret =
          find(reqUrl, child, pos + fragment.size(), params);
      update_found(ret);
    }
  }

  if (node->paramChildrens[static_cast<size_t>(ParamType::INT)] != 0U) {
    char c = reqUrl[pos];
    if ((c >= '0' && c <= '9') || c == '+' || c == '-') {
      char* eptr = nullptr;
      errno = 0;
      int64_t value = std::strtoll(reqUrl.data() + pos, &eptr, 10);  // NOLINT
      if (errno != ERANGE && eptr != reqUrl.data() + pos) {
        params->intParams.push_back(value);
        std::pair<unsigned, RoutingParams> ret = find(
            reqUrl,
            &nodes[node->paramChildrens[static_cast<size_t>(ParamType::INT)]],
            static_cast<size_t>(eptr - reqUrl.data()), params);
        update_found(ret);
        params->intParams.pop_back();
      }
    }
  }

  if (node->paramChildrens[static_cast<size_t>(ParamType::UINT)] != 0U) {
    char c = reqUrl[pos];
    if ((c >= '0' && c <= '9') || c == '+') {
      char* eptr = nullptr;
      errno = 0;
      uint64_t value = std::strtoull(reqUrl.data() + pos, &eptr, 10);  // NOLINT
      if (errno != ERANGE && eptr != reqUrl.data() + pos) {
        params->uintParams.push_back(value);
        std::pair<unsigned, RoutingParams> ret = find(
            reqUrl,
            &nodes[node->paramChildrens[static_cast<size_t>(ParamType::UINT)]],
            static_cast<size_t>(eptr - reqUrl.data()), params);
        update_found(ret);
        params->uintParams.pop_back();
      }
    }
  }

  if (node->paramChildrens[static_cast<size_t>(ParamType::DOUBLE)] != 0U) {
    char c = reqUrl[pos];
    if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.') {
      char* eptr = nullptr;
      errno = 0;
      double value = std::strtod(reqUrl.data() + pos, &eptr);
      if (errno != ERANGE && eptr != reqUrl.data() + pos) {
        params->doubleParams.push_back(value);
        std::pair<unsigned, RoutingParams> ret =
            find(reqUrl,
                 &nodes[node->paramChildrens[static_cast<size_t>(
                     ParamType::DOUBLE)]],
                 static_cast<size_t>(eptr - reqUrl.data()), params);
        update_found(ret);
        params->doubleParams.pop_back();
      }
    }
  }

  if (node->paramChildrens[static_cast<size_t>(ParamType::STRING)] != 0U) {
    size_t epos = pos;
    for (; epos < reqUrl.size(); epos++) {
      if (reqUrl[epos] == '/') {
        break;
      }
    }

    if (epos != pos) {
      params->stringParams.emplace_back(reqUrl.substr(pos, epos - pos));
      std::pair<unsigned, RoutingParams> ret = find(
          reqUrl,
          &nodes[node->paramChildrens[static_cast<size_t>(ParamType::STRING)]],
          epos, params);
      update_found(ret);
      params->stringParams.pop_back();
    }
  }

  if (node->paramChildrens[static_cast<size_t>(ParamType::PATH)] != 0U) {
    size_t epos = reqUrl.size();

    if (epos != pos) {
      params->stringParams.emplace_back(reqUrl.substr(pos, epos - pos));
      std::pair<unsigned, RoutingParams> ret = find(
          reqUrl,
          &nodes[node->paramChildrens[static_cast<size_t>(ParamType::PATH)]],
          epos, params);
      update_found(ret);
      params->stringParams.pop_back();
    }
  }

  return {found, match_params};
}

void Trie::add(const std::string& url, unsigned int ruleIndex) {
  size_t idx = 0;

  for (unsigned i = 0; i < url.size(); i++) {
    char c = url[i];
    if (c == '<') {
      static const std::array<std::pair<ParamType, std::string>, 7>
          // NOLINTNEXTLINE
          paramTraits = {{
              {ParamType::INT, "<int>"},
              {ParamType::UINT, "<uint>"},
              {ParamType::DOUBLE, "<float>"},
              {ParamType::DOUBLE, "<double>"},
              {ParamType::STRING, "<str>"},
              {ParamType::STRING, "<string>"},
              {ParamType::PATH, "<path>"},
          }};

      for (const std::pair<ParamType, std::string>& x : paramTraits) {
        if (url.compare(i, x.second.size(), x.second) == 0) {
          size_t index = static_cast<size_t>(x.first);
          if (nodes[idx].paramChildrens[index] == 0U) {
            unsigned new_node_idx = newNode();
            nodes[idx].paramChildrens[index] = new_node_idx;
          }
          idx = nodes[idx].paramChildrens[index];
          i += static_cast<unsigned>(x.second.size());
          break;
        }
      }

      i--;
    } else {
      std::string piece(&c, 1);
      if (nodes[idx].children.count(piece) == 0U) {
        unsigned new_node_idx = newNode();
        nodes[idx].children.emplace(piece, new_node_idx);
      }
      idx = nodes[idx].children[piece];
    }
  }
  if (nodes[idx].ruleIndex != 0U) {
    throw std::runtime_error("handler already exists for " + url);
  }
  nodes[idx].ruleIndex = ruleIndex;
}

void Trie::debugNodePrint(Node* n, size_t level)

{
  for (size_t i = 0; i < static_cast<size_t>(ParamType::MAX); i++) {
    if (n->paramChildrens[i] != 0U) {
      BMCWEB_LOG_DEBUG << std::string(
          2U * level, ' ') /*<< "("<<n->paramChildrens[i]<<") "*/;
      switch (static_cast<ParamType>(i)) {
        case ParamType::INT:
          BMCWEB_LOG_DEBUG << "<int>";
          break;
        case ParamType::UINT:
          BMCWEB_LOG_DEBUG << "<uint>";
          break;
        case ParamType::DOUBLE:
          BMCWEB_LOG_DEBUG << "<float>";
          break;
        case ParamType::STRING:
          BMCWEB_LOG_DEBUG << "<str>";
          break;
        case ParamType::PATH:
          BMCWEB_LOG_DEBUG << "<path>";
          break;
        case ParamType::MAX:
          BMCWEB_LOG_DEBUG << "<ERROR>";
          break;
      }

      debugNodePrint(&nodes[n->paramChildrens[i]], level + 1);
    }
  }
  for (const Node::ChildMap::value_type& kv : n->children) {
    BMCWEB_LOG_DEBUG << std::string(2U * level,
                                    ' ') /*<< "(" << kv.second << ") "*/
                     << kv.first;
    debugNodePrint(&nodes[kv.second], level + 1);
  }
}

void Router::internalAddRuleObject(const std::string& rule,
                                   BaseRule* ruleObject) {
  if (ruleObject == nullptr) {
    return;
  }
  for (size_t method = 0, method_bit = 1; method <= methodNotAllowedIndex;
       method++, method_bit <<= 1) {
    if ((ruleObject->methodsBitfield & method_bit) > 0U) {
      perMethods[method].rules.push_back(ruleObject);
      perMethods[method].trie.add(
          rule, static_cast<unsigned>(perMethods[method].rules.size() - 1U));
      // directory case:
      //   request to `/about' url matches `/about/' rule
      if (rule.size() > 2 && rule.back() == '/') {
        perMethods[method].trie.add(
            rule.substr(0, rule.size() - 1),
            static_cast<unsigned>(perMethods[method].rules.size() - 1));
      }
    }
  }
}

void Router::validate() {
  for (std::unique_ptr<BaseRule>& rule : allRules) {
    if (rule) {
      std::unique_ptr<BaseRule> upgraded = rule->upgrade();
      if (upgraded) {
        rule = std::move(upgraded);
      }
      rule->validate();
      internalAddRuleObject(rule->rule, rule.get());
    }
  }
  for (PerMethod& per_method : perMethods) {
    per_method.trie.validate();
  }
}

Router::FindRoute Router::findRouteByIndex(std::string_view url,
                                           size_t index) const {
  FindRoute route;
  if (index >= perMethods.size()) {
    BMCWEB_LOG_CRITICAL << "Bad index???";
    return route;
  }
  const PerMethod& per_method = perMethods[index];
  std::pair<unsigned, RoutingParams> found = per_method.trie.find(url);
  if (found.first >= per_method.rules.size()) {
    throw std::runtime_error("Trie internal structure corrupted!");
  }
  // Found a 404 route, switch that in
  if (found.first != 0U) {
    route.rule = per_method.rules[found.first];
    route.params = std::move(found.second);
  }
  return route;
}

Router::FindRouteResponse Router::findRoute(Request& req) const {
  FindRouteResponse find_route;

  std::optional<HttpVerb> verb = httpVerbFromBoost(req.method());
  if (!verb) {
    return find_route;
  }
  size_t req_method_index = static_cast<size_t>(*verb);
  // Check to see if this url exists at any verb
  for (size_t per_method_index = 0; per_method_index <= maxVerbIndex;
       per_method_index++) {
    // Make sure it's safe to deference the array at that index
    static_assert(maxVerbIndex < std::tuple_size_v<decltype(perMethods)>);
    FindRoute route =
        findRouteByIndex(req.url().encoded_path(), per_method_index);
    if (route.rule == nullptr) {
      continue;
    }
    if (!find_route.allowHeader.empty()) {
      find_route.allowHeader += ", ";
    }
    HttpVerb this_verb = static_cast<HttpVerb>(per_method_index);
    find_route.allowHeader += httpVerbToString(this_verb);
    if (per_method_index == req_method_index) {
      find_route.route = route;
    }
  }
  return find_route;
}

bool Router::isAccessAllowedFromInsecureTransport(const Request& req,
                                                  std::string_view url_str) {
  // Allow all GET requests
  if (req.method() == boost::beast::http::verb::get) {
    return true;
  }

  ecclesia::ResourceEntity entity =
      ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance()
          .GetEntityTypeFromRedfishUri(url_str);

  // Allow PATCH to ComputerSystems
  // /redfish/v1/Systems/{systemId}
  if (entity == ecclesia::ResourceEntity::kComputerSystem &&
      req.method() == boost::beast::http::verb::patch) {
    return true;
  }

  // Allow all operations to BootOption and BootOptionCollection
  // This is so that the host can set boot options
  if (entity == ecclesia::ResourceEntity::kBootOptionCollection ||
      entity == ecclesia::ResourceEntity::kBootOption) {
    return true;
  }

  return false;
}

bool Router::needsAuthorization(const Request& req, std::string_view url_str) {
  // Always require authorization if req.fromGrpc is true.
  if (req.fromGrpc) {
    return true;
  }

  // We know its insecure and if we are not restricting redfish routes from
  // insecure transport, no need to authorize
  if (!restrictRedfishRoutesFromInsecureTransport) {
    return false;
  }

  // if authenticated and configured to skip authz, then skip authz.
  if (insecureDisableGrpcRedfishAuthz && req.peer_authenticated) {
    return false;
  }

  // Otherwise, require authorization if access is not allowed from insecure
  // transport.
  return !isAccessAllowedFromInsecureTransport(req, url_str);
}

void Router::handle(Request& req,
                    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
  std::optional<HttpVerb> verb = httpVerbFromBoost(req.method());
  if (!verb || static_cast<size_t>(*verb) >= perMethods.size()) {
    asyncResp->res.result(boost::beast::http::status::not_found);
    return;
  }

  FindRouteResponse found_route = findRoute(req);

  if (found_route.route.rule == nullptr && catch_all_rule_ == nullptr) {
    // Couldn't find a normal route with any verb, try looking for a 404
    // route
    if (found_route.allowHeader.empty()) {
      found_route.route =
          findRouteByIndex(req.url().encoded_path(), notFoundIndex);
    } else {
      // See if we have a method not allowed (405) handler
      found_route.route =
          findRouteByIndex(req.url().encoded_path(), methodNotAllowedIndex);
    }
  } else if (found_route.route.rule == nullptr) {
    // We found a catch all rule, so we should use that
    found_route.route.rule = catch_all_rule_.get();
  }

  // Fill in the allow header if it's valid
  if (!found_route.allowHeader.empty()) {
    asyncResp->res.addHeader(boost::beast::http::field::allow,
                             found_route.allowHeader);
  }

  // If we couldn't find a real route or a 404 route, return a generic
  // response
  if (found_route.route.rule == nullptr) {
    if (found_route.allowHeader.empty()) {
      asyncResp->res.result(boost::beast::http::status::not_found);
    } else {
      asyncResp->res.result(boost::beast::http::status::method_not_allowed);
    }
    return;
  }

  BaseRule& rule = *found_route.route.rule;
  RoutingParams params = std::move(found_route.route.params);

  BMCWEB_LOG_INFO << "Matched rule '" << rule.rule << "' "
                  << static_cast<uint32_t>(*verb) << " / " << rule.getMethods();

#ifdef BMCWEB_ENABLE_GRPC

  std::string_view url_str = {req.url().encoded_path().data(),
                              req.url().encoded_path().size()};

  if (needsAuthorization(req, req.url().encoded_path())) {
    // Handles dynamic fine-grained authorization
    ::milotic::authz::BmcWebAuthorizerSingleton::RequestState authz_state;
    authz_state.with_trust_bundle = req.with_trust_bundle;
    authz_state.peer_authenticated = req.peer_authenticated;
    authz_state.peer_privileges = req.peer_privileges;

    grpc::Status status =
        ::milotic::authz::BmcWebAuthorizerSingleton::GetInstance().Authorize(
            url_str, req.method(), authz_state);

    if (!status.ok()) {
      asyncResp->res.addHeader("OData-Version", "4.0");
      LOG(WARNING) << "Authorization failure at " << req.url() << ": "
                   << status.error_message();
      ::redfish::messages::resourceAtUriUnauthorized(asyncResp->res, req.url(),
                                                     status.error_message());
      return;
    }
  }

  rule.handle(req, asyncResp, params);
#else
  validatePrivilege(req, asyncResp, rule,
                    [&rule, asyncResp, params](Request& thisReq) mutable {
                      rule.handle(thisReq, asyncResp, params);
                    });
#endif
}

void Router::debugPrint() {
  for (size_t i = 0; i < perMethods.size(); i++) {
    BMCWEB_LOG_DEBUG << boost::beast::http::to_string(
        static_cast<boost::beast::http::verb>(i));
    perMethods[i].trie.debugPrint();
  }
}

std::vector<const std::string*> Router::getRoutes(const std::string& parent)

{
  std::vector<const std::string*> ret;

  for (const PerMethod& pm : perMethods) {
    std::vector<unsigned> x;
    pm.trie.findRouteIndexes(parent, x);
    for (unsigned index : x) {
      ret.push_back(&pm.rules[index]->rule);
    }
  }
  return ret;
}

void Router::throwHandlerNotFound(std::string_view url,
                                  boost::beast::http::verb boostVerb) {
  std::string error = "handler doesn't exist for ";
  error += url;
  error += ", method ";
  error += boostVerbToString(boostVerb);
  throw std::runtime_error(error);
}

}  // namespace crow
