#include "tlbmc/redfish/routes/chassis.h"

#include <algorithm>
#include <functional>
#include <string>
#include <utility>
#include <vector>

#include "absl/functional/bind_front.h"
#include "absl/log/log.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "nlohmann/json.hpp"
#include "nlohmann/json_fwd.hpp"
#include "tlbmc/central_config/config.h"
#include "topology_config.pb.h"
#include "tlbmc/redfish/app.h"
#include "tlbmc/redfish/data/stable_id.h"
#include "stable_id.pb.h"
#include "tlbmc/redfish/request.h"
#include "tlbmc/redfish/response.h"
#include "tlbmc/redfish/url.h"
#include "fru.pb.h"
#include "resource.pb.h"
#include "tlbmc/store/store.h"
#include "google/protobuf/repeated_ptr_field.h"

namespace milotic_tlbmc::chassis {

namespace {

void HandleChassisCollection(const RedfishApp& app, const RedfishRequest& req,
                             RedfishResponse& resp) {
  resp.SetKeyInJsonBody("/@odata.id", "/redfish/v1/Chassis");
  resp.SetKeyInJsonBody("/@odata.type", "#ChassisCollection.ChassisCollection");
  resp.SetKeyInJsonBody("/Name", "Chassis Collection");

  const Store& store = *app.GetStore();
  absl::StatusOr<std::vector<std::string>> config_keys =
      store.GetAllConfigKeys();
  if (!config_keys.ok()) {
    resp.SetToAbslStatus(config_keys.status());
    return;
  }

  std::vector<std::string> chassis_ids;
  for (const auto& key : *config_keys) {
    absl::StatusOr<std::string> fru_key = store.GetFruKeyByConfigKey(key);
    if (!fru_key.ok()) {
      continue;
    }
    absl::StatusOr<const Fru*> fru = store.GetFru(*fru_key);
    if (!fru.ok()) {
      LOG(WARNING) << "Failed to get FRU with key " << *fru_key
                   << " from store: " << fru.status();
      continue;
    }

    if ((*fru)->attributes().resource_type() != RESOURCE_TYPE_BOARD) {
      continue;
    }

    chassis_ids.push_back(key);
  }
  std::sort(chassis_ids.begin(), chassis_ids.end());

  nlohmann::json::array_t members = nlohmann::json::array_t();
  for (const auto& id : chassis_ids) {
    nlohmann::json::object_t member;
    member["@odata.id"] = CreateUrl({"redfish", "v1", "Chassis", id});
    members.push_back(std::move(member));
  }
  resp.SetKeyInJsonBody("/Members", members);
  resp.SetKeyInJsonBody("/Members@odata.count", chassis_ids.size());
}

void HandleChassis(const RedfishApp& app, const RedfishRequest& req,
                   RedfishResponse& resp, const std::string& chassis_id) {
  const Store& store = *app.GetStore();
  nlohmann::json::json_pointer chassis_pointer("");
  // Chassis id corresponds to the config key.
  absl::StatusOr<std::string> fru_key = store.GetFruKeyByConfigKey(chassis_id);
  if (!fru_key.ok()) {
    resp.SetToAbslStatus(fru_key.status());
    return;
  }

  absl::StatusOr<const Fru*> fru = store.GetFru(*fru_key);
  if (!fru.ok()) {
    resp.SetToAbslStatus(fru.status());
    return;
  }
  absl::StatusOr<const TopologyConfigNode*> topology_config_node =
      store.GetFruTopology(chassis_id);
  if (!topology_config_node.ok()) {
    resp.SetToAbslStatus(topology_config_node.status());
    return;
  }
  FillResponseWithFruData(chassis_pointer, *fru, *topology_config_node, resp);
}

inline std::string GetSystemId() { return "system"; }

nlohmann::json::array_t CreateChildResourceLinksArray(
    const ::google::protobuf::RepeatedPtrField<std::string>& child_resource_ids,
    ResourceType resource_type) {
  nlohmann::json::array_t child_resources;
  for (const auto& id : child_resource_ids) {
    nlohmann::json::object_t child_object;
    switch (resource_type) {
      case RESOURCE_TYPE_BOARD:
        child_object["@odata.id"] = CreateUrl({"redfish", "v1", "Chassis", id});
        break;
      case RESOURCE_TYPE_CABLE:
        child_object["@odata.id"] = CreateUrl({"redfish", "v1", "Cables", id});
        break;
      case RESOURCE_TYPE_PROCESSOR:
        child_object["@odata.id"] = CreateUrl(
            {"redfish", "v1", "Systems", GetSystemId(), "Processors", id});
        break;
      case RESOURCE_TYPE_STORAGE:
        child_object["@odata.id"] = CreateUrl(
            {"redfish", "v1", "Systems", GetSystemId(), "Storage", id});
        break;
      default:
        break;
    }
    child_resources.emplace_back(child_object);
  }
  return child_resources;
}
}  // namespace

void FillResponseWithFruData(
    const nlohmann::json::json_pointer& chassis_pointer, const Fru* fru_ptr,
    const TopologyConfigNode* topology_config_node_ptr, RedfishResponse& resp) {
  const std::string& chassis_id = topology_config_node_ptr->name();

  if (fru_ptr->attributes().status() != STATUS_READY) {
    resp.SetToNotReady(
        absl::StrFormat("Chassis %s is not ready in tlBMC Store", chassis_id));
    return;
  }
  resp.SetKeyInJsonBody(chassis_pointer / "@odata.id",
                        "/redfish/v1/Chassis/" + chassis_id);
  resp.SetKeyInJsonBody(chassis_pointer / "@odata.type",
                        "#Chassis.v1_17_0.Chassis");
  resp.SetKeyInJsonBody(
      chassis_pointer / "Assembly" / "@odata.id",
      CreateUrl({"redfish", "v1", "Chassis", chassis_id, "Assembly"}));
  resp.SetKeyInJsonBody(
      chassis_pointer / "Certificates" / "@odata.id",
      CreateUrl({"redfish", "v1", "Chassis", chassis_id, "Certificates"}));
  resp.SetKeyInJsonBody(
      chassis_pointer / "TrustedComponents" / "@odata.id",
      milotic_tlbmc::CreateUrl(
          {"redfish", "v1", "Chassis", chassis_id, "TrustedComponents"}));
  absl::string_view chassis_type;
  switch (fru_ptr->attributes().chassis_properties().chassis_type()) {
    case CHASSIS_TYPE_RACK_MOUNT:
      chassis_type = "RackMount";
      break;
    case CHASSIS_TYPE_MODULE:
      chassis_type = "Module";
      break;
    case CHASSIS_TYPE_STORAGE_ENCLOSURE:
      chassis_type = "StorageEnclosure";
      break;
    case CHASSIS_TYPE_COMPONENT:
      chassis_type = "Component";
      break;
    case CHASSIS_TYPE_STANDALONE:
      chassis_type = "StandAlone";
      break;
    default:
      break;
  }
  resp.SetKeyInJsonBody(chassis_pointer / "ChassisType", chassis_type);

  if (fru_ptr->attributes().chassis_properties().bmcnet()) {
    resp.SetKeyInJsonBody(
        chassis_pointer / "NetworkAdapters" / "@odata.id",
        milotic_tlbmc::CreateUrl(
            {"redfish", "v1", "Chassis", chassis_id, "NetworkAdapters"}));
  }

  // Support Chassis Reset Action only for Root Chassis.
  if (topology_config_node_ptr->location_context().devpath() == "/phys" ||
      topology_config_node_ptr->location_context().devpath() ==
          absl::StrCat(
              "/", topology_config_node_ptr->root_chassis_location_code())) {
    resp.SetKeyInJsonBody(
        chassis_pointer / "Actions" / "#Chassis.Reset" / "target",
        CreateUrl({"redfish", "v1", "Chassis", chassis_id, "Actions",
                   "Chassis.Reset"}));
    resp.SetKeyInJsonBody(
        chassis_pointer / "Actions" / "#Chassis.Reset" / "@Redfish.ActionInfo",
        CreateUrl({"redfish", "v1", "Chassis", chassis_id, "ResetActionInfo"}));
  }
  resp.SetKeyInJsonBody(
      chassis_pointer / "Drives" / "@odata.id",
      CreateUrl({"redfish", "v1", "Chassis", chassis_id, "Drives"}));
  resp.SetKeyInJsonBody(
      chassis_pointer / "Memory" / "@odata.id",
      CreateUrl({"redfish", "v1", "Systems", GetSystemId(), "Memory"}));
  resp.SetKeyInJsonBody(chassis_pointer / "Id", chassis_id);
  resp.SetKeyInJsonBody(chassis_pointer / "Name", chassis_id);
  resp.SetKeyInJsonBody(
      chassis_pointer / "Sensors" / "@odata.id",
      CreateUrl({"redfish", "v1", "Chassis", chassis_id, "Sensors"}));

  // Only populate Thermal if Thermal Control is disabled.
  if (!GetTlbmcConfig()
           .sensor_collector_module()
           .thermal_control_sub_module()
           .enabled()) {
    resp.SetKeyInJsonBody(
        chassis_pointer / "Thermal" / "@odata.id",
        CreateUrl({"redfish", "v1", "Chassis", chassis_id, "Thermal"}));
  }

  resp.SetKeyInJsonBody(
      chassis_pointer / "ThermalSubsystem" / "@odata.id",
      CreateUrl({"redfish", "v1", "Chassis", chassis_id, "ThermalSubsystem"}));

  resp.SetKeyInJsonBody(
      chassis_pointer / "Power" / "@odata.id",
      CreateUrl({"redfish", "v1", "Chassis", chassis_id, "Power"}));
  resp.SetKeyInJsonBody(
      chassis_pointer / "PowerSubsystem" / "@odata.id",
      CreateUrl({"redfish", "v1", "Chassis", chassis_id, "PowerSubsystem"}));

  resp.SetKeyInJsonBody(chassis_pointer / "EnvironmentMetrics" / "@odata.id",
                        CreateUrl({"redfish", "v1", "Chassis", chassis_id,
                                   "EnvironmentMetrics"}));

  resp.SetKeyInJsonBody(chassis_pointer / "PowerState", "On");

  resp.SetKeyInJsonBody(chassis_pointer / "PCIeDevices" / "@odata.id",
                        "/redfish/v1/Systems/system/PCIeDevices");
  resp.SetKeyInJsonBody(
      chassis_pointer / "PCIeSlots" / "@odata.id",
      CreateUrl({"redfish", "v1", "Chassis", chassis_id, "PCIeSlots"}));

  if (fru_ptr->data().has_asset_info()) {
    const AssetInfo& asset_info = fru_ptr->data().asset_info();
    if (!asset_info.manufacturer().empty()) {
      resp.SetKeyInJsonBody(chassis_pointer / "Manufacturer",
                            asset_info.manufacturer());
    }
    if (!asset_info.product_name().empty()) {
      resp.SetKeyInJsonBody(chassis_pointer / "Model",
                            asset_info.product_name());
    }
    if (!asset_info.serial_number().empty()) {
      resp.SetKeyInJsonBody(chassis_pointer / "SerialNumber",
                            asset_info.serial_number());
    }
    if (!asset_info.part_number().empty()) {
      resp.SetKeyInJsonBody(chassis_pointer / "PartNumber",
                            asset_info.part_number());
    }
  }

  if (topology_config_node_ptr->has_location_context()) {
    StableId stable_id = GetStableId(*topology_config_node_ptr);

    if (!stable_id.service_label().empty()) {
      resp.SetKeyInJsonBody(
          chassis_pointer / "Location" / "PartLocation" / "ServiceLabel",
          stable_id.service_label());
      if (stable_id.has_location_type()) {
        absl::string_view location_type;
        switch (stable_id.location_type()) {
          case PART_LOCATION_TYPE_BACKPLANE:
            location_type = "Backplane";
            break;
          case PART_LOCATION_TYPE_BAY:
            location_type = "Bay";
            break;
          case PART_LOCATION_TYPE_EMBEDDED:
            location_type = "Embedded";
            break;
          case PART_LOCATION_TYPE_SLOT:
            location_type = "Slot";
            break;
          case PART_LOCATION_TYPE_SOCKET:
            location_type = "Socket";
            break;
          default:
            break;
        }
        if (!location_type.empty()) {
          resp.SetKeyInJsonBody(
              chassis_pointer / "Location" / "PartLocation" / "LocationType",
              location_type);
        }
      }
    }
    if (!stable_id.part_location_context().empty() &&
        stable_id.part_location_context() != "phys") {
      resp.SetKeyInJsonBody(
          chassis_pointer / "Location" / "PartLocationContext",
          stable_id.part_location_context());
    }
    if (stable_id.has_embedded_location_context()) {
      resp.SetKeyInJsonBody(chassis_pointer / "Location" / "Oem" / "Google" /
                                "EmbeddedLocationContext",
                            stable_id.embedded_location_context());
    }
    // Populate special devpath field for embedded chassis.
    if (stable_id.location_type() == PART_LOCATION_TYPE_EMBEDDED) {
      resp.SetKeyInJsonBody(
          chassis_pointer / "Location" / "Oem" / "Google" / "Devpath",
          stable_id.machine_local_devpath());
    }
  }

  nlohmann::json::array_t child_chassis = CreateChildResourceLinksArray(
      topology_config_node_ptr->children_chassis_ids(), RESOURCE_TYPE_BOARD);
  if (!child_chassis.empty()) {
    resp.SetKeyInJsonBody(chassis_pointer / "Links" / "Contains",
                          child_chassis);
    resp.SetKeyInJsonBody(chassis_pointer / "Links" / "Contains@odata.count",
                          child_chassis.size());
  }

  nlohmann::json::array_t child_cables = CreateChildResourceLinksArray(
      topology_config_node_ptr->children_cable_ids(), RESOURCE_TYPE_CABLE);
  nlohmann::json::array_t parent_cables = CreateChildResourceLinksArray(
      topology_config_node_ptr->parent_cable_ids(), RESOURCE_TYPE_CABLE);
  nlohmann::json::array_t all_cables;
  all_cables.insert(all_cables.end(), child_cables.begin(), child_cables.end());
  all_cables.insert(all_cables.end(), parent_cables.begin(),
                    parent_cables.end());
  if (!all_cables.empty()) {
    resp.SetKeyInJsonBody(chassis_pointer / "Links" / "Cables", all_cables);
    resp.SetKeyInJsonBody(chassis_pointer / "Links" / "Cables@odata.count",
                          all_cables.size());
  }

  // Processors are stored as a map to avoid conflicting processor ids on
  // different chassis. We must iterate over the map to get all keys.
  ::google::protobuf::RepeatedPtrField<std::string> processor_ids;
  for (const auto& [processor_id, _] :
       topology_config_node_ptr->children_processors()) {
    processor_ids.Add(std::string(processor_id));
  }
  std::sort(processor_ids.pointer_begin(), processor_ids.pointer_end(),
            [](const std::string* id_1, const std::string* id_2) {
              return *id_1 < *id_2;
            });
  nlohmann::json::array_t child_processors =
      CreateChildResourceLinksArray(processor_ids, RESOURCE_TYPE_PROCESSOR);
  if (!child_processors.empty()) {
    resp.SetKeyInJsonBody(chassis_pointer / "Links" / "Processors",
                          child_processors);
    resp.SetKeyInJsonBody(chassis_pointer / "Links" / "Processors@odata.count",
                          child_processors.size());
  }

  nlohmann::json::array_t child_storages = CreateChildResourceLinksArray(
      topology_config_node_ptr->children_storage_ids(), RESOURCE_TYPE_STORAGE);
  if (!child_storages.empty()) {
    resp.SetKeyInJsonBody(chassis_pointer / "Links" / "Storage",
                          child_storages);
    resp.SetKeyInJsonBody(chassis_pointer / "Links" / "Storage@odata.count",
                          child_storages.size());
  }

  if (topology_config_node_ptr->has_parent_resource_id()) {
    resp.SetKeyInJsonBody(
        chassis_pointer / "Links" / "ContainedBy" / "@odata.id",
        CreateUrl({"redfish", "v1", "Chassis",
                   topology_config_node_ptr->parent_resource_id()}));
  }

  nlohmann::json::array_t managed_by;
  nlohmann::json::object_t manager;
  manager["@odata.id"] = "/redfish/v1/Managers/bmc";
  managed_by.emplace_back(manager);
  resp.SetKeyInJsonBody(chassis_pointer / "Links" / "ManagedBy", managed_by);

  // TODO(davtang): Add support for multihost systems
  nlohmann::json::array_t systems;
  nlohmann::json::object_t system;
  system["@odata.id"] = "/redfish/v1/Systems/system";
  systems.emplace_back(system);
  resp.SetKeyInJsonBody(chassis_pointer / "Links" / "ComputerSystems", systems);

  resp.SetKeyInJsonBody(chassis_pointer / "Status" / "Health", "OK");
  resp.SetKeyInJsonBody(chassis_pointer / "Status" / "HealthRollup", "OK");
  resp.SetKeyInJsonBody(chassis_pointer / "Status" / "State", "Enabled");
}

void RegisterRoutes(RedfishApp& app) {
  TLBMC_ROUTE(app, "/redfish/v1/Chassis/")
      .methods(boost::beast::http::verb::get)(
          absl::bind_front(HandleChassisCollection, std::cref(app)));
  TLBMC_ROUTE(app, "/redfish/v1/Chassis/<str>/")
      .methods(boost::beast::http::verb::get)(
          absl::bind_front(HandleChassis, std::cref(app)));
}

}  // namespace milotic_tlbmc::chassis
