#include "smart_router.h"

#include <cstddef>
#include <iostream>
#include <memory>
#include <string>
#include <string_view>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/str_split.h"
#include "absl/synchronization/mutex.h"
#include "http_request.hpp"
#include "async_resp.hpp"
#include "tlbmc/hal/shared_mem/server.h"
#include "tlbmc/redfish/verb.h"
#include "app_interface.h"
#include "routing.hpp"

// DO NOT MODIFY THIS FILE IN GERRIT. THIS FILE SHOULD ONLY BE MODIFIED IN G3

namespace crow {

using ::milotic_tlbmc::SharedMemoryServer;

namespace internal {

void SimpleTrie::AddSubtree(std::string_view subtree) {
  std::vector<std::string_view> parts =
      absl::StrSplit(subtree, '/', absl::SkipEmpty());
  Node* node = &root_;
  for (const auto& part : parts) {
    node = &node->children[part];
  }
  node->is_leaf = true;
}

SimpleTrie::SimpleTrie(const absl::flat_hash_set<std::string>& subtrees)
    : subtrees_(subtrees) {
  for (const auto& subtree : subtrees) {
    AddSubtree(subtree);
  }
}

void SimpleTrie::DebugPrint() const {
  std::cerr << "tlBMC owned subtrees: \n";
  for (const auto& subtree : subtrees_) {
    std::cerr << subtree << "\n";
  }
}

bool SimpleTrie::IsUrlInSubtrees(std::string_view url) const {
  const Node* node = &root_;
  std::vector<std::string_view> parts =
      absl::StrSplit(url, '/', absl::SkipEmpty());
  for (const auto& part : parts) {
    if (node->is_leaf) {
      return true;
    }
    auto it = node->children.find(part);
    if (it == node->children.end()) {
      return false;
    }
    node = &it->second;
  }
  return node->is_leaf;
}

}  // namespace internal

SmartRouter::SmartRouter(bool allow_session_empty, AppInterface* tlbmc_app)
    : gbmcweb_router_(allow_session_empty),
      tlbmc_app_(tlbmc_app),
      tlbmc_owned_urls_(GetTlbmcOwnedUrls()),
      tlbmc_owned_subtrees_(GetTlbmcOwnedSubtrees()) {
  // We still need this logic to set the smart router for the tlbmc router.
  if (tlbmc_app_ != nullptr) {
    tlbmc_app_->SetSmartRouter(this);
    std::cerr << "SmartRouter created! Owned URLs: \n";
    for (const auto& [url, methods] : tlbmc_owned_urls_) {
      std::cerr << "url: " << url
                << " methods: " << milotic_tlbmc::MethodFieldsToString(methods)
                << "\n";
    }
  }
}

void SmartRouter::Handle(crow::Request& req,
                         const std::shared_ptr<bmcweb::AsyncResp>& async_resp) {
  boost::urls::url url(req.target());

  // If the request is not owned by TLBMC, then we will forward it to gBMCWeb.
  if (tlbmc_app_ == nullptr ||
      !IsTlbmcOwnedUrl(url.encoded_path(), req.method())) {
    gbmcweb_router_.handle(req, async_resp);
    if (tlbmc_app_ != nullptr) {
      SharedMemoryServer::GetInstance().UpdateMetricsRequestCount(false);
    }
    return;
  }

  // Otherwise we prepare for tlbmc to handle it.
  SharedMemoryServer::GetInstance().UpdateMetricsRequestCount(true);
  tlbmc_app_->HandleFromCrowRequest(req, async_resp);
}

std::vector<const std::string*> SmartRouter::GetRoutes(
    const std::string& parent) {
  return gbmcweb_router_.getRoutes(parent);
}

DynamicRule& SmartRouter::NewRuleDynamic(std::string&& rule) {
  return gbmcweb_router_.newRuleDynamic(rule);
}

void SmartRouter::DebugPrint() {
  gbmcweb_router_.debugPrint();
  if (tlbmc_app_ != nullptr) {
    tlbmc_app_->DebugPrint();
  }
}

void SmartRouter::Validate() { gbmcweb_router_.validate(); }

absl::flat_hash_map<std::string, size_t> SmartRouter::GetTlbmcOwnedUrls() {
  if (tlbmc_app_ == nullptr) {
    return {};
  }
  return tlbmc_app_->GetOwnedUrls();
}

absl::flat_hash_set<std::string> SmartRouter::GetTlbmcOwnedSubtrees() {
  if (tlbmc_app_ == nullptr) {
    return {};
  }
  return tlbmc_app_->GetOwnedSubtrees();
}

bool SmartRouter::IsTlbmcOwnedUrl(std::string_view url,
                                  boost::beast::http::verb verb) {
  // Our `tlbmc_owned_urls_` do not have a trailing slash
  if (url.ends_with('/')) {
    url.remove_suffix(1);
  }
  if (tlbmc_owned_subtrees_.IsUrlInSubtrees(url)) {
    return true;
  }
  // NOLINTNEXTLINE: Yocto's Abseil is old and only supports pointer type
  absl::MutexLock lock(&tlbmc_owned_urls_mutex_);
  auto it = tlbmc_owned_urls_.find(url);
  if (it == tlbmc_owned_urls_.end()) {
    return false;
  }
  return milotic_tlbmc::MethodFieldsContainBoostVerb(it->second, verb);
}

void SmartRouter::UpdateTlbmcOwnedUrls() {
  // NOLINTNEXTLINE: Yocto's Abseil is old and only supports pointer type
  absl::MutexLock lock(&tlbmc_owned_urls_mutex_);
  tlbmc_owned_urls_ = GetTlbmcOwnedUrls();
}

}  // namespace crow
