#include "tlbmc/service/fru_service.h"

#include <array>
#include <memory>
#include <string>
#include <system_error>  // NOLINT
#include <utility>
#include <vector>

#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/log/log.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.h"
#include "g3/macros.h"
#include "grpcpp/security/auth_context.h"
#include "grpcpp/server_context.h"
#include "grpcpp/support/server_callback.h"
#include "grpcpp/support/status.h"
#include "nlohmann/json_fwd.hpp"
#include "json_utils.h"
#include "fru_component_model.pb.h"
#include "fru_service.pb.h"
#include "app.hpp"
#include "dbus_utility.hpp" // NOLINT
#include "async_resp.hpp" // NOLINT
#include "http_request.hpp" // NOLINT
#include "zatar/bmcweb_cert_provider.h"

namespace milotic_fast_sanity {

namespace {

using ::grpc::AuthContext;
using ::grpc::CallbackServerContext;
using ::grpc::ServerUnaryReactor;
using ::milotic::authz::GetValueAsJson;
using ::milotic::authz::GetValueAsString;

constexpr absl::string_view kRootChassisUrl = "/redfish/v1/Chassis?$expand=.";
// TODO(b/415893570): Make this config-based.
// Be ware: BB has `"/redfish/v1/Systems/system1/Memory"` as the memory
// Redfish path.
constexpr std::array<absl::string_view, 5> kRootUrls = {
    "/redfish/v1/Chassis?$expand=.($levels=2)",
    "/redfish/v1/Cables?$expand=.($levels=1)",
    "/redfish/v1/Systems/system/Storage?$expand=.($levels=1)",
    "/redfish/v1/Systems/system/Memory?$expand=.($levels=1)",
    "/redfish/v1/Systems/system/Processors?$expand=.($levels=2)"};
// local_devpath3 = "/" + LocalRootChassisLocationCode + PartLocationContext +
//                  ServiceLabel
constexpr absl::string_view kLocalRootChassisLocationCode = "phys";

// TODO(b/422818770): Add a test case for this util function.
// Create Internal Request to query given `url`.
absl::StatusOr<crow::Request> CreateRedfishRequest(
    absl::string_view url, boost::beast::http::verb method) {
  boost::beast::http::request<boost::beast::http::string_body> boost_request;
  boost_request.target(url);
  // TODO(b/422818770): Add the server & client pair.
  boost_request.method(method);
  std::error_code error;
  crow::Request crow_request(boost_request, error);
  if (error) {
    return absl::InternalError("Error creating crow_request.");
  }

  crow_request.fromGrpc = false;
  return crow_request;
}

absl::Status IsLocationInfoValid(const nlohmann::json &fru) {
  // TODO(b/422818770): Add a test case to cover the missing
  // location info case.
  const nlohmann::json *fru_location = GetValueAsJson(fru, "Location");
  if (fru_location == nullptr) {
    return absl::NotFoundError("Location info not found.");
  }

  const nlohmann::json *fru_location_part_location =
      GetValueAsJson(*fru_location, "PartLocation");
  if (fru_location_part_location == nullptr) {
    return absl::NotFoundError("Location.PartLocation info not found.");
  }

  const nlohmann::json *fru_location_part_location_service_label =
      GetValueAsJson(*fru_location_part_location, "ServiceLabel");
  if (fru_location_part_location_service_label == nullptr) {
    return absl::NotFoundError(
        "Location.PartLocation.ServiceLabel info not found.");
  }

  return absl::OkStatus();
}

absl::StatusOr<std::string> ExtractRootChassisLocationCodeFromJson(
    const nlohmann::json &json) {
  if (!json.contains("Members")) {
    return absl::InternalError(
        "Redfish response does not contain `Members` field.");
  }

  for (const auto &fru : json["Members"]) {
    // The root node's indegree must be 0.
    if (fru.contains("Links") && fru["Links"].contains("ContainedBy")) {
      continue;
    }

    // Make sure there is valid location info.
    if (!IsLocationInfoValid(fru).ok()) {
      continue;
    }

    return *GetValueAsString(fru["Location"]["PartLocation"], "ServiceLabel");
  }

  // Certain machines don't have a Root Chassis Location Code
  return "";
}

absl::StatusOr<Devpath> ExtractDevpathFromJson(
    const nlohmann::json &json, absl::string_view root_chassis_location_code) {
  // TODO(b/422818770): Add a test case to cover the missing
  // location info case.
  ECCLESIA_RETURN_IF_ERROR(IsLocationInfoValid(json));

  // Ensure this is a FRU.
  const auto location_type_it =
      json["Location"]["PartLocation"].find("LocationType");
  if (location_type_it == json["Location"]["PartLocation"].end() ||
      (*location_type_it) != "Slot") {
    return Devpath();
  }

  // This is the root chassis. Return empty devpath.
  const auto &res_member_location = json["Location"];
  std::string service_label =
      res_member_location["PartLocation"]["ServiceLabel"];
  if (service_label == root_chassis_location_code) {
    return Devpath();
  }

  // PartLocationContext is optional, and the prefix should be removed if it is
  // equal to the root chassis location code.
  std::string part_location_context;
  const auto part_location_context_it =
      res_member_location.find("PartLocationContext");
  if (part_location_context_it != res_member_location.end()) {
    part_location_context = res_member_location.at("PartLocationContext");
  }
  bool start_with_root_chassis_location_code =
      !root_chassis_location_code.empty() &&
      absl::StartsWith(part_location_context, root_chassis_location_code);
  bool start_with_local_root_chassis_location_code =
      absl::StartsWith(part_location_context, kLocalRootChassisLocationCode);
  if (start_with_root_chassis_location_code ||
      start_with_local_root_chassis_location_code) {
    // Note that RootChassisLocationCode should be eliminated if it is the
    // prefix of either `PartLocationContext` or `ServiceLabel`.
    part_location_context =
        start_with_root_chassis_location_code
            ? part_location_context.substr(root_chassis_location_code.length())
            : part_location_context.substr(
                  kLocalRootChassisLocationCode.length());
  }

  return Devpath(part_location_context, service_label);
}

void InsertDevpath(const nlohmann::json &json,
                   absl::string_view root_chassis_location_code,
                   std::shared_ptr<PartLocationContextToServiceLabelSet>
                       &part_location_context_to_service_label_set) {
  absl::StatusOr<Devpath> devpath_status =
      ExtractDevpathFromJson(json, root_chassis_location_code);
  // TODO(b/422818770): Utilize the error status better.
  //  E.g., provide logs.
  if (!devpath_status.ok() || devpath_status.value().service_label.empty()) {
    return;
  }

  absl::MutexLock lock(&part_location_context_to_service_label_set->mutex);
  part_location_context_to_service_label_set
      ->part_location_context_to_service_label_set[devpath_status.value()
                                                       .part_location_context]
      .insert(devpath_status.value().service_label);
}

void GenerateDevpathFromRedfishObject(
    const nlohmann::json &json, absl::string_view root_chassis_location_code,
    std::shared_ptr<PartLocationContextToServiceLabelSet>
        part_location_context_to_service_label_set) {
  InsertDevpath(json, root_chassis_location_code,
                part_location_context_to_service_label_set);
  const auto assembly_it = json.find("Assembly");
  if (assembly_it != json.end() &&
      assembly_it->find("Assemblies") != json["Assembly"].end()) {
    for (const auto &fru : (*assembly_it)["Assemblies"]) {
      GenerateDevpathFromRedfishObject(
          fru, root_chassis_location_code,
          part_location_context_to_service_label_set);
    }
  }
  if (json.contains("Members")) {
    for (const auto &fru : json["Members"]) {
      GenerateDevpathFromRedfishObject(
          fru, root_chassis_location_code,
          part_location_context_to_service_label_set);
    }
  }
}

void SendGetAllFruInfoResponse(
    ServerUnaryReactor &reactor, GetAllFruInfoResponse &response,
    const std::shared_ptr<PartLocationContextToServiceLabelSet>
        &part_location_context_to_service_label_set) {
  // Build the devpath list
  // Insert the default local root chassis devpath first.
  std::vector<std::string> devpaths({"/phys"});

  {
    absl::MutexLock lock(&part_location_context_to_service_label_set->mutex);
    for (const auto &[part_location_context, service_label_set] :
         part_location_context_to_service_label_set
             ->part_location_context_to_service_label_set) {
      for (const auto &service_label : service_label_set) {
        devpaths.push_back(absl::StrCat(
            "/", kLocalRootChassisLocationCode, "/",
            (!part_location_context.empty() ? part_location_context + "/" : ""),
            service_label));
      }
    }
  }

  if (devpaths.empty()) {
    reactor.Finish(::grpc::Status(::grpc::StatusCode::INTERNAL,
                                  "No matched devpath found."));
  }

  for (const std::string &devpath : devpaths) {
    if (devpath.empty()) {
      continue;
    }
    FruComponent fru;
    fru.mutable_primary_identifier()->set_value(devpath);
    fru.mutable_primary_identifier()->set_type(
        UniqueIdentifierType::UNIQUE_IDENTIFIER_TYPE_LOCAL_DEVPATH);
    response.mutable_fru_components()->Add(std::move(fru));
  }
  reactor.Finish(::grpc::Status(::grpc::StatusCode::OK, "Devpath list sent."));
}

void DecreaseOngoingDevpathExtractionRequestCount(
    const std::shared_ptr<OngoingDevpathExtractionRequestCount>
        &ongoing_devpath_extraction_request_count) {
  absl::MutexLock lock(&ongoing_devpath_extraction_request_count->mutex);
  --ongoing_devpath_extraction_request_count
        ->ongoing_devpath_extraction_request_count;
}

}  // namespace

FruServiceImpl::FruServiceImpl(App *app, const FruServiceOptions &options)
    : app_(app),
      has_trust_bundle_(options.cert_provider->GetServerStatus() ==
                            ::milotic::redfish::BmcWebCertProvider::
                                ServerStatus::kWithRootCertsAndProdSignedCert ||
                        options.cert_provider->GetServerStatus() ==
                            ::milotic::redfish::BmcWebCertProvider::
                                ServerStatus::kWithRootCertsAndSelfSignedCert) {
}

::grpc::Status FruServiceImpl::RequestIsAuthenticated(
    const AuthContext *auth_context) const {
  // Perform Authentication
  // If the server has no trust bundle, then fail fast sanity.
  if (!has_trust_bundle_) {
    return ::grpc::Status(::grpc::StatusCode::UNAUTHENTICATED,
                          "Server has no trust bundle, failing fast sanity.");
  }

  // If peer is no authenticated, then return an error.
  if (!auth_context->IsPeerAuthenticated()) {
    return ::grpc::Status(
        ::grpc::StatusCode::UNAUTHENTICATED,
        absl::StrFormat("Peer %s is not authenticated.",
                        auth_context->GetPeerIdentityPropertyName()));
  }
  return ::grpc::Status(::grpc::StatusCode::OK, "Peer is authenticated.");
}

ServerUnaryReactor *FruServiceImpl::GetAllFruInfo(
    CallbackServerContext *context, const GetAllFruInfoRequest *request,
    GetAllFruInfoResponse *response) {
  ServerUnaryReactor *reactor = context->DefaultReactor();

  if (::grpc::Status status =
          RequestIsAuthenticated(context->auth_context().get());
      !status.ok()) {
    reactor->Finish(status);
    return reactor;
  }

  GenerateMatchedDevpathsFromRedfishPaths(*reactor, *request, *response);
  return reactor;
}

void FruServiceImpl::GenerateMatchedDevpathsFromRedfishPaths(
    ServerUnaryReactor &reactor, const GetAllFruInfoRequest &request,
    GetAllFruInfoResponse &response) {
  // Extract the root chassis location code from the first url.
  absl::StatusOr<crow::Request> crow_request_status =
      CreateRedfishRequest(kRootChassisUrl, boost::beast::http::verb::get);
  if (!crow_request_status.ok()) {
    LOG(WARNING) << "Error creating redfish request for url: `"
                 << kRootChassisUrl << "`; with status: `"
                 << crow_request_status.status() << "`";
    reactor.Finish(
        ::grpc::Status(::grpc::StatusCode::INTERNAL,
                       absl::StrCat("Error creating redfish request for "
                                    "root chassis location code url: `",
                                    kRootChassisUrl, "`.")));
    return;
  }

  auto async_resp = std::make_shared<bmcweb::AsyncResp>(nullptr);
  async_resp->response_type =
      bmcweb::AsyncResp::ResponseType::kOriginOfCondition;
  async_resp->res.setCompleteRequestHandler([this, &reactor, &request,
                                             &response](crow::Response &res) {
    if (!res.stringResponse.has_value()) {
      reactor.Finish(
          ::grpc::Status(::grpc::StatusCode::INTERNAL,
                         absl::StrCat("No valid response from redfish "
                                      "for root chassis url: `",
                                      kRootChassisUrl, "`.")));
      return;
    }
    absl::StatusOr<std::string> root_chassis_location_code_status =
        ExtractRootChassisLocationCodeFromJson(res.jsonValue);
    if (!root_chassis_location_code_status.ok()) {
      reactor.Finish(::grpc::Status(
          ::grpc::StatusCode::INTERNAL,
          std::string(root_chassis_location_code_status.status().message())));
      return;
    }

    RequestRedfishAndExtractDevpaths(reactor, request, response,
                                     *root_chassis_location_code_status);
  });
  app_->handle(*crow_request_status, async_resp);
}

void FruServiceImpl::RequestRedfishAndExtractDevpaths(
    ServerUnaryReactor &reactor, const GetAllFruInfoRequest &request,
    GetAllFruInfoResponse &response,
    absl::string_view root_chassis_location_code) {
  std::shared_ptr<PartLocationContextToServiceLabelSet>
      part_location_context_to_service_label_set =
          std::make_shared<PartLocationContextToServiceLabelSet>();

  std::shared_ptr<OngoingDevpathExtractionRequestCount>
      ongoing_devpath_extraction_request_count =
          std::make_shared<OngoingDevpathExtractionRequestCount>(
              kRootUrls.size());

  for (absl::string_view url : kRootUrls) {
    absl::StatusOr<crow::Request> devpath_request_status =
        CreateRedfishRequest(url, boost::beast::http::verb::get);
    if (!devpath_request_status.ok()) {
      LOG(WARNING) << "Error creating redfish request for url: `" << url
                   << "`; with status: `" << devpath_request_status.status()
                   << "`";
      continue;
    }
    auto async_devpath_resp = std::make_shared<bmcweb::AsyncResp>(nullptr);
    async_devpath_resp->response_type =
        bmcweb::AsyncResp::ResponseType::kOriginOfCondition;

    // Extract devpaths from the rest of the requests.
    async_devpath_resp->res.setCompleteRequestHandler(
        [&reactor, &response, url, part_location_context_to_service_label_set,
         root_chassis_location_code = std::string(root_chassis_location_code),
         ongoing_devpath_extraction_request_count](crow::Response &res) {
          if (res.stringResponse.has_value()) {
            GenerateDevpathFromRedfishObject(
                res.jsonValue, root_chassis_location_code,
                part_location_context_to_service_label_set);
          } else {
            LOG(WARNING) << "No valid response from redfish for url: `" << url
                         << "`";
          }

          DecreaseOngoingDevpathExtractionRequestCount(
              ongoing_devpath_extraction_request_count);

          absl::MutexLock lock(
              &ongoing_devpath_extraction_request_count->mutex);
          if (ongoing_devpath_extraction_request_count
                  ->ongoing_devpath_extraction_request_count == 0) {
            SendGetAllFruInfoResponse(
                reactor, response, part_location_context_to_service_label_set);
          }
        });
    app_->handle(*devpath_request_status, async_devpath_resp);
  }
}

}  // namespace milotic_fast_sanity
