#include "app.hpp"
#include "async_resp.hpp"
#include "dbus_utility.hpp"
#include "http_request.hpp"
#include "http_response.hpp"
#include "managers.hpp"
#include "snapshot_fixture.hpp"

#include <nlohmann/json.hpp>

#include <gmock/gmock.h>
#include <gtest/gtest.h>

namespace redfish
{
namespace
{

using ::dbus::utility::DBusPropertiesMap;
using ::dbus::utility::DbusVariantType;
using ::dbus::utility::MapperGetSubTreeResponse;
using ::dbus::utility::MapperServiceMap;
using ::managedStore::KeyType;
using ::managedStore::ManagedType;
using ::managedStore::ValueType;

const std::string kClassType = "Temperature";
const std::string kSensor = "sensor0";
constexpr double kInput = 43.0;
constexpr double kOutput = 4000.0;
constexpr double kSetpoint = 65.0;
constexpr uint8_t kTestData = 15;

std::shared_ptr<ValueType> CreateMockSubtreeResponse()
{
    MapperGetSubTreeResponse mockSubtreeResponse{{std::make_pair(
        "/xyz/openbmc_project/inventory/system/component/BMC_flash",
        MapperServiceMap{{std::make_pair(
            "xyz.openbmc_project.EntityManager",
            std::vector<std::string>{
                "xyz.openbmc_project.Inventory.Decorator.LocationCode"})}})}};
    return managedStore::MockManagedStoreTest::CreateValueType(
        std::move(mockSubtreeResponse));
}

TEST_F(SnapshotFixture, handleManagerGetTest)
{
    KeyType key(ManagedType::kManagedSubtree, "/xyz/openbmc_project/inventory",
                0, {"xyz.openbmc_project.Inventory.Item.Bmc"});
    ASSERT_TRUE(
        managedStore::GetManagedObjectStore()
            ->upsertMockObjectIntoManagedStore(key, CreateMockSubtreeResponse())
            .ok());
    handleManagerGet(app_, CreateRequest(), share_async_resp_);

    RunIoUntilDone();

    nlohmann::json& json = share_async_resp_->res.jsonValue;

    LOG(INFO) << json.dump(2);
    EXPECT_EQ(json["@odata.id"], "/redfish/v1/Managers/bmc");
    EXPECT_EQ(json["Location"]["PartLocation"]["ServiceLabel"], "BMC");
    EXPECT_EQ(json["Location"]["PartLocation"]["LocationType"], "Embedded");
    EXPECT_EQ(json["Location"]["PartLocationContext"], "DC_SCM");
    EXPECT_EQ(json["Location"]["Oem"]["Google"]["EmbeddedLocationContext"],
              "openbmc_manager");
    EXPECT_EQ(share_async_resp_->res.result(), boost::beast::http::status::ok);
}

std::shared_ptr<ValueType> CreatePidDebugInfoProperty()
{
    DBusPropertiesMap pidDebugInfoProperty{
        {std::make_pair("ClassType", DbusVariantType(kClassType))},
        {std::make_pair("Input", DbusVariantType(kInput))},
        {std::make_pair("Leader", DbusVariantType(kSensor))},
        {std::make_pair("Output", DbusVariantType(kOutput))},
        {std::make_pair("Setpoint", DbusVariantType(kSetpoint))},
        {std::make_pair("TestData", DbusVariantType(kTestData))}};
    return managedStore::MockManagedStoreTest::CreateValueType(
        std::move(pidDebugInfoProperty));
}

TEST_F(SnapshotFixture, updateZoneLeaderInfoGetNull)
{
    const std::string zoneIndex = "0";
    const std::string name = "Zone_0";
    const std::string leader = "sensor_PID";
    const std::string pidDebugInfoPath =
        "/xyz/openbmc_project/settings/fanctrl/zone" + zoneIndex + "/" + leader;

    auto response = std::make_shared<bmcweb::AsyncResp>();
    nlohmann::json& json = response->res.jsonValue;
    managedStore::ManagedObjectStoreContext context(response);

    // Test for null dbus response
    updateZoneLeaderInfo(response, zoneIndex, name, leader, context);

    RunIoUntilDone();

    EXPECT_TRUE(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["ClassType"]
            .is_null());
    EXPECT_TRUE(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["Input"]
            .is_null());
    EXPECT_TRUE(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["Output"]
            .is_null());
    EXPECT_TRUE(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["Sensor"]
            .is_null());
    EXPECT_TRUE(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["Setpoint"]
            .is_null());
}

TEST_F(SnapshotFixture, updateZoneLeaderInfoSuccess)
{
    const std::string zoneIndex = "0";
    const std::string name = "Zone_0";
    const std::string leader = "sensor_PID";
    const std::string pidDebugInfoPath =
        "/xyz/openbmc_project/settings/fanctrl/zone" + zoneIndex + "/" + leader;

    auto response = std::make_shared<bmcweb::AsyncResp>();
    nlohmann::json& json = response->res.jsonValue;
    managedStore::ManagedObjectStoreContext context(response);

    // kManagedPropertyMap
    KeyType key(ManagedType::kManagedPropertyMap,
                "xyz.openbmc_project.State.FanCtrl", pidDebugInfoPath,
                "xyz.openbmc_project.Debug.Pid.ThermalPower");

    ASSERT_TRUE(managedStore::GetManagedObjectStore()
                    ->upsertMockObjectIntoManagedStore(
                        key, CreatePidDebugInfoProperty())
                    .ok());

    updateZoneLeaderInfo(response, zoneIndex, name, leader, context);

    RunIoUntilDone();

    EXPECT_EQ(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["ClassType"],
        kClassType);
    EXPECT_EQ(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["Input"],
        kInput);
    EXPECT_EQ(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["Sensor"],
        kSensor);
    EXPECT_EQ(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["Output"],
        kOutput);
    EXPECT_EQ(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["Setpoint"],
        kSetpoint);
    EXPECT_EQ(
        json["Oem"]["OpenBmc"]["Fan"]["FanZones"][name]["Leader"]["TestData"],
        "n/a");
}

TEST_F(SnapshotFixture, PostManagerResetActionGood){
// using expected call to mitigate the memory issue in valgrind
// https://b.corp.google.com/issues/416295689
// https://b.corp.google.com/issues/416608762
    EXPECT_CALL(*managedStore::GetManagedObjectStore(),
                PostDbusCallToIoContextThreadSafe(
                    testing::_,
                    testing::An<absl::AnyInvocable<void(const boost::system::error_code&)>&&>(),
                    "xyz.openbmc_project.State.Chassis",
                    testing::An<const std::string&>(),
                    "org.freedesktop.DBus.Properties",
                    "Set",
                    "xyz.openbmc_project.State.Chassis",
                    "RequestedPowerTransition",
                    dbus::utility::DbusVariantType("xyz.openbmc_project.State.Chassis.Transition.PowerCycle")
                ))
        .WillOnce(
            managedStore::SimulateSuccessfulAsyncPostDbusCallThreadSafeAction::
            SimulateSuccessfulAsyncPostDbusCall());

    handlePostManagerResetAction(app_, CreateRequest("{\"ResetType\":\"TrayPowerCycle\"} "), share_async_resp_);

    RunIoUntilDone();

    EXPECT_EQ(share_async_resp_->res.result(),boost::beast::http::status::ok);
}

TEST_F(SnapshotFixture, PostManagerResetActionBadResetType){
    handlePostManagerResetAction(app_, CreateRequest("{\"ResetType\":\"Typo\"} "), share_async_resp_);

    RunIoUntilDone();

    EXPECT_EQ(share_async_resp_->res.result(),boost::beast::http::status::bad_request);
}

TEST_F(SnapshotFixture, handleManagerResetActionInfoAllowableValues){
    handleManagerResetActionInfo(app_, CreateRequest(""), share_async_resp_);

    RunIoUntilDone();

    EXPECT_EQ(share_async_resp_->res.result(),boost::beast::http::status::ok);

    auto allowable_values = share_async_resp_->res.jsonValue["Parameters"][0]["AllowableValues"];
    EXPECT_THAT(allowable_values, testing::ElementsAre("GracefulRestart", "ForceRestart", "TrayPowerCycle"));
}

} // namespace
} // namespace redfish
