#include "redfish_devpath_injector.hpp"

#include <fstream>
#include <memory>
#include <string>
#include <string_view>
#include <system_error>  // NOLINT

#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_cat.h"
#include "boost/beast/http/status.hpp"  // NOLINT
#include "boost/beast/http/verb.hpp"  // NOLINT
#include "http_request.hpp"
#include "http_response.hpp"
#include <nlohmann/json.hpp>

using ::testing::status::StatusIs;

namespace devpath_plugin {
namespace {

std::string WriteTmpFile(std::string_view name, std::string_view content) {
  std::string path = absl::StrCat(testing::TempDir(), "/", name);
  std::ofstream out(path);
  out << content;
  out.close();
  return path;
}

crow::Request CreateRequest(
    std::string_view path,
    boost::beast::http::verb method = boost::beast::http::verb::get) {
  std::error_code ec;
  crow::Request req(std::string_view(""), ec);
  req.set_method(method);
  req.target(path);
  return req;
}

TEST(RedfishDevpathInjectorTest, LoadValidConfigSuccess) {
  std::string config_content = R"pb(
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/RootOfTrustCollection/RotA" }
      uhm_monitored_component_key { barepath: "/phys/BoardA:device:rot_a" }
      redfish_expose_config {
        expose_oem_google_devpath: true
        set_plc_as_placeholder: false
        embedded_location_context: "rot_context_a"
      }
    }
  )pb";
  std::string config_path =
      WriteTmpFile("valid_config.textproto", config_content);

  ASSERT_OK(RedfishDevpathInjector::Create(config_path).status());
}

TEST(RedfishDevpathInjectorTest, LoadInvalidConfigReturnsError) {
  std::string invalid_config_path =
      WriteTmpFile("invalid_config.textproto", "invalid_content");
  EXPECT_THAT(RedfishDevpathInjector::Create(invalid_config_path),
              StatusIs(absl::StatusCode::kInvalidArgument));
}

TEST(RedfishDevpathInjectorTest, NonExistentConfigReturnsError) {
  EXPECT_THAT(
      RedfishDevpathInjector::Create("/path/to/non_existent_file.textproto"),
      StatusIs(absl::StatusCode::kNotFound));
}

TEST(RedfishDevpathInjectorTest, InjectValidMappingSuccess) {
  std::string config_content = R"pb(
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/RootOfTrustCollection/RotA" }
      uhm_monitored_component_key { barepath: "/phys/BoardA:device:rot_a" }
      redfish_expose_config {
        expose_oem_google_devpath: true
        set_plc_as_placeholder: false
        embedded_location_context: "rot_context_a"
      }
    }
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/Chassis/ChassisA" }
      uhm_monitored_component_key { barepath: "/phys/BoardA" }
      redfish_expose_config {
        expose_oem_google_devpath: false
        set_plc_as_placeholder: true
      }
    }
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/Chassis/ChassisB" }
      uhm_monitored_component_key { barepath: "/phys/BoardA" }
      redfish_expose_config {
        expose_oem_google_devpath: false
        set_plc_as_placeholder: false
      }
    }
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/Chassis/ChassisA/Drives/Drive0" }
      uhm_monitored_component_key { barepath: "/phys/BoardA/SLOT0" }
      redfish_expose_config {
        expose_oem_google_devpath: true
        set_plc_as_placeholder: false
        use_physical_location: true
      }
    }
  )pb";
  std::string config_path =
      WriteTmpFile("injectable_config.textproto", config_content);

  absl::StatusOr<std::unique_ptr<RedfishDevpathInjector>> injector =
      RedfishDevpathInjector::Create(config_path);
  ASSERT_OK(injector.status());

  // Test Component 1 with :device:
  {
    crow::Request req = CreateRequest("/redfish/v1/RootOfTrustCollection/RotA");
    crow::Response res;
    res.result(boost::beast::http::status::ok);

    (*injector)->Inject(req, res);

    const nlohmann::json& json = res.jsonValue;
    EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "rot_a");
    EXPECT_EQ(json["Location"]["PartLocationContext"], "BoardA");
    EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"],
              "/phys/BoardA:device:rot_a");
    EXPECT_EQ(json["Location"]["Oem"]["Google"]["EmbeddedLocationContext"],
              "rot_context_a");
  }

  // Test Component 2 without :device: and with placeholder plc
  {
    crow::Request req = CreateRequest("/redfish/v1/Chassis/ChassisA");
    crow::Response res;
    res.result(boost::beast::http::status::ok);

    (*injector)->Inject(req, res);

    nlohmann::json json = res.jsonValue;
    EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "BoardA");
    EXPECT_EQ(json["Location"]["PartLocationContext"],
              "PlaceholderAndShouldNotBeUsed");

    EXPECT_FALSE(json["Location"]["Oem"]["Google"].contains("Devpath"));
    EXPECT_FALSE(
        json["Location"]["Oem"]["Google"].contains("EmbeddedLocationContext"));
  }

  // Test Component 3 where PLC is empty and shouldn't appear
  {
    crow::Request req = CreateRequest("/redfish/v1/Chassis/ChassisB");
    crow::Response res;
    res.result(boost::beast::http::status::ok);

    (*injector)->Inject(req, res);

    nlohmann::json json = res.jsonValue;
    EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "BoardA");
    EXPECT_FALSE(json["Location"].contains("PartLocationContext"));
  }

  // Test Component 4 with use_physical_location enabled
  {
    crow::Request req =
        CreateRequest("/redfish/v1/Chassis/ChassisA/Drives/Drive0");
    crow::Response res;
    res.result(boost::beast::http::status::ok);

    (*injector)->Inject(req, res);

    EXPECT_EQ(res.jsonValue, nlohmann::json::parse(R"json(
      {
        "PhysicalLocation": {
          "Oem": {
            "Google": {
              "Devpath": "/phys/BoardA/SLOT0"
            }
          },
          "PartLocation": {
            "ServiceLabel": "SLOT0"
          },
          "PartLocationContext": "BoardA"
        }
      }
    )json"));
  }
}

TEST(RedfishDevpathInjectorTest,
     InjectPhysicalLocationOverridesPreexistingFields) {
  std::string config_content = R"pb(
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/Chassis/ChassisA/Drives/Drive1" }
      uhm_monitored_component_key { barepath: "/phys/HPM0/DOWNLINK/PE1A/SLOT2" }
      redfish_expose_config {
        expose_oem_google_devpath: true
        set_plc_as_placeholder: false
        use_physical_location: true
      }
    }
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/Chassis/ChassisA/Drives/Drive2" }
      uhm_monitored_component_key { barepath: "/phys/SLOT0" }
      redfish_expose_config {
        expose_oem_google_devpath: false
        set_plc_as_placeholder: false
        use_physical_location: true
      }
    }
  )pb";
  std::string config_path =
      WriteTmpFile("override_config.textproto", config_content);

  absl::StatusOr<std::unique_ptr<RedfishDevpathInjector>> injector =
      RedfishDevpathInjector::Create(config_path);
  ASSERT_OK(injector.status());

  // Case 1: Pre-existing wrong Devpath and placeholder PLC from handler are
  // overwritten when expose_oem_google_devpath is true.
  {
    crow::Request req =
        CreateRequest("/redfish/v1/Chassis/ChassisA/Drives/Drive1");
    crow::Response res;
    res.result(boost::beast::http::status::ok);
    res.jsonValue = nlohmann::json::parse(R"json(
      {
        "PhysicalLocation": {
          "Oem": {
            "Google": {
              "Devpath": "/phys/HPM0/DOWNLINK/PE1A/DOWNLINK"
            }
          },
          "PartLocationContext": "PlaceHolderAndShouldNotBeUsed"
        }
      }
    )json");

    (*injector)->Inject(req, res);

    EXPECT_EQ(res.jsonValue, nlohmann::json::parse(R"json(
      {
        "PhysicalLocation": {
          "Oem": {
            "Google": {
              "Devpath": "/phys/HPM0/DOWNLINK/PE1A/SLOT2"
            }
          },
          "PartLocation": {
            "ServiceLabel": "SLOT2"
          },
          "PartLocationContext": "HPM0/DOWNLINK/PE1A"
        }
      }
    )json"));
  }

  // Case 2: Pre-existing placeholder PLC is erased when part_location_context
  // is empty and set_plc_as_placeholder is false.
  {
    crow::Request req =
        CreateRequest("/redfish/v1/Chassis/ChassisA/Drives/Drive2");
    crow::Response res;
    res.result(boost::beast::http::status::ok);
    res.jsonValue = nlohmann::json::parse(R"json(
      {
        "PhysicalLocation": {
          "PartLocationContext": "PlaceHolderAndShouldNotBeUsed"
        }
      }
    )json");

    (*injector)->Inject(req, res);

    EXPECT_EQ(res.jsonValue, nlohmann::json::parse(R"json(
      {
        "PhysicalLocation": {
          "PartLocation": {
            "ServiceLabel": "SLOT0"
          }
        }
      }
    )json"));
  }
}

TEST(RedfishDevpathInjectorTest, InjectNonGetRequestReturnsNoOp) {
  std::string config_content = R"pb(
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/RootOfTrustCollection/RotA" }
      uhm_monitored_component_key { barepath: "/phys/BoardA:device:rot_a" }
    }
  )pb";
  std::string config_path =
      WriteTmpFile("nonget_config.textproto", config_content);

  absl::StatusOr<std::unique_ptr<RedfishDevpathInjector>> injector =
      RedfishDevpathInjector::Create(config_path);
  ASSERT_OK(injector.status());

  crow::Request req = CreateRequest("/redfish/v1/RootOfTrustCollection/RotA",
                                    boost::beast::http::verb::post);
  crow::Response res;
  res.result(boost::beast::http::status::ok);

  (*injector)->Inject(req, res);

  EXPECT_TRUE(res.jsonValue.empty());
}

TEST(RedfishDevpathInjectorTest, InjectNonOkStatusReturnsNoOp) {
  std::string config_content = R"pb(
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/RootOfTrustCollection/RotA" }
      uhm_monitored_component_key { barepath: "/phys/BoardA:device:rot_a" }
    }
  )pb";
  std::string config_path =
      WriteTmpFile("nonok_config.textproto", config_content);

  absl::StatusOr<std::unique_ptr<RedfishDevpathInjector>> injector =
      RedfishDevpathInjector::Create(config_path);
  ASSERT_OK(injector.status());

  crow::Request req = CreateRequest("/redfish/v1/RootOfTrustCollection/RotA");
  crow::Response res;
  res.result(boost::beast::http::status::not_found);

  (*injector)->Inject(req, res);

  EXPECT_TRUE(res.jsonValue.empty());
}

TEST(RedfishDevpathInjectorTest, InjectNonExistentUrlReturnsNoOp) {
  std::string config_content = R"pb(
    redfish_to_uhm_mapping {
      key { redfish_url_pattern: "/redfish/v1/RootOfTrustCollection/RotA" }
      uhm_monitored_component_key { barepath: "/phys/BoardA:device:rot_a" }
    }
  )pb";
  std::string config_path =
      WriteTmpFile("nonexistent_config.textproto", config_content);

  absl::StatusOr<std::unique_ptr<RedfishDevpathInjector>> injector =
      RedfishDevpathInjector::Create(config_path);
  ASSERT_OK(injector.status());

  crow::Request req =
      CreateRequest("/redfish/v1/RootOfTrustCollection/DeviceB");
  crow::Response res;
  res.result(boost::beast::http::status::ok);

  (*injector)->Inject(req, res);

  EXPECT_TRUE(res.jsonValue.empty());
}

TEST(RedfishDevpathInjectorTest, InjectRegexMappingSuccess) {
  std::string config_content = R"pb(
    redfish_to_uhm_mapping {
      key {
        redfish_url_pattern: "/redfish/v1/Systems/system/Storage/StorageModuleA/Controllers/[0-9]+"
      }
      uhm_monitored_component_key {
        barepath: "/phys/SlotA:device:controller_a"
      }
      redfish_expose_config {
        expose_oem_google_devpath: true
        set_plc_as_placeholder: false
        embedded_location_context: "controller:0"
      }
    }
  )pb";
  std::string config_path =
      WriteTmpFile("regex_config.textproto", config_content);

  absl::StatusOr<std::unique_ptr<RedfishDevpathInjector>> injector =
      RedfishDevpathInjector::Create(config_path);
  ASSERT_OK(injector.status());

  // Test correct match
  {
    crow::Request req = CreateRequest(
        "/redfish/v1/Systems/system/Storage/StorageModuleA/Controllers/0");
    crow::Response res;
    res.result(boost::beast::http::status::ok);

    (*injector)->Inject(req, res);

    const nlohmann::json& json = res.jsonValue;
    EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "controller_a");
    EXPECT_EQ(json["Location"]["PartLocationContext"], "SlotA");
    EXPECT_EQ(json["Location"]["Oem"]["Google"]["Devpath"],
              "/phys/SlotA:device:controller_a");
    EXPECT_EQ(json["Location"]["Oem"]["Google"]["EmbeddedLocationContext"],
              "controller:0");
  }

  // Test path not fitting the regex
  {
    crow::Request req = CreateRequest(
        "/redfish/v1/Systems/system/Storage/StorageModuleA/Controllers/abc");
    crow::Response res;
    res.result(boost::beast::http::status::ok);

    (*injector)->Inject(req, res);

    EXPECT_TRUE(res.jsonValue.empty());
  }
}

}  // namespace
}  // namespace devpath_plugin
