#include "absl/strings/match.h"
#include "managed_store_http.hpp"

#include <malloc.h>

#include "logging.hpp"
#include "managed_store.hpp"
#include "managed_store_clock.hpp"
#include "managed_store_types.hpp"
#include "query.hpp"

#include <nlohmann/json.hpp>

#include <algorithm>
#include <charconv>
#include <string_view>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace managedStore
{

void ManagedObjectStoreHttp::requestRoutesManagedStoreDebug(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    // playing with the header:
    auto maxAgeSec = 0;
    const auto maxAgeSecStr =
        req.getHeaderValue(bmcweb::BMCWEB_HINT_MAX_AGE_SEC);
    if (!maxAgeSecStr.empty())
    {
        std::from_chars(maxAgeSecStr.data(),
                        maxAgeSecStr.data() + maxAgeSecStr.size(), maxAgeSec);
    }

    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> /debug/managed_store: target: " << req.target()
        << " method: " << req.method() << " body: " << req.body()
        << " maxAgeSecStr: " << maxAgeSecStr << " maxAgeSec: " << maxAgeSec;

    // ManagedObjectStore instance:
    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }

    // config:
    asyncResp->res.jsonValue["config"] = store->getConfig().toJson();

    // objects:
    asyncResp->res.jsonValue["managed_objects_metrics"] =
        store->GetManagedObjectsMetrics(managedStore::clockNow());

    // serialized size:
    asyncResp->res.jsonValue["snapshot_size_in_bytes"] =
        store->GetSnapshotSizeInBytes();

    // Export pq entries:
    store->GetPriorityQueueSize([asyncResp](size_t size) {
        asyncResp->res.jsonValue["managed_objects_pq_size"] = size;
    });
    store->GetPriorityQueueMetrics([asyncResp](const nlohmann::json& metrics) {
        asyncResp->res.jsonValue["managed_objects_pq_entries"] = metrics;
    });

    // ManagedStore counters from managedStoreTracker
    const ManagedStoreTracker& storeTracker = store->getStoreTracker();
    asyncResp->res.jsonValue["tracker"] = storeTracker.toJson();

    // always keep this one as the last item:
    asyncResp->res.jsonValue["ok"] = true;
}

void ManagedObjectStoreHttp::requestRoutesManagedStorePostFlush(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> /debug/managed_store: target: " << req.target()
        << " method: " << req.method() << " body: " << req.body();

    // ManagedObjectStore instance:
    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }

    asyncResp->res.jsonValue["config"] = store->getConfig().toJson();
    store->clearAllObjects();
    asyncResp->res.jsonValue["managed_objects_metrics"] =
        store->GetManagedObjectsMetrics(managedStore::clockNow());
    store->GetPriorityQueueSize([asyncResp](size_t size) {
        asyncResp->res.jsonValue["managed_objects_pq_size"] = size;
    });

    // always keep this one as the last item:
    asyncResp->res.jsonValue["ok"] = true;
}

void ManagedObjectStoreHttp::requestRoutesSubscriptionsDebug(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> /debug/subscriptions: target: " << req.target()
        << " method: " << req.method() << " body: " << req.body();

    // ManagedObjectStore instance:
    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }

    asyncResp->res.jsonValue["SubscriptionStore"] =
        store->GetSubscriptionsToJSON();
    asyncResp->res.jsonValue["DBusMonitors"] = store->GetDBusMonitorsToJSON();
}

void ManagedObjectStoreHttp::requestRoutesEventStoreDebug(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> /debug/event_store: target: " << req.target()
        << " method: " << req.method() << " body: " << req.body();

    // ManagedObjectStore instance:
    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }

    std::string_view target = req.target();
    auto startIndex = target.find('?');
    if (startIndex != std::string::npos)
    {
        // The query has query params
        auto subIdIndex = target.find("subscription_id=", startIndex);
        if (subIdIndex == std::string::npos || subIdIndex != startIndex + 1)
        {
            asyncResp->res.jsonValue["Error"] =
                "Invalid query param. Only subscription_id param is supported.";
            return;
        }
        auto len = strlen("subscription_id=");
        std::string_view subscription_id = target.substr(subIdIndex + len);
        if (subscription_id.empty() || absl::StrContains(subscription_id, '?'))
        {
            asyncResp->res.jsonValue["Error"] =
                "Invalid query params. Only subscription_id param is supported.";
            return;
        }
        BMCWEB_LOG_STATEFUL_DEBUG << "subscription_id = " << subscription_id;
        size_t id = 0;
        if (1 == sscanf(subscription_id.data(), "%zu", &id)) // NOLINT
        {
            asyncResp->res.jsonValue =
                store->GetEventsBySubscriptionIdToJSON(id);
            return;
        }
        asyncResp->res.jsonValue["Error"] = "Invalid subscription_id.";
        return;
    }
    asyncResp->res.jsonValue = store->GetEventsToJSON();
}

void ManagedObjectStoreHttp::requestRoutesEventStoreFlush(
    const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> /debug/event_store: target: " << req.target()
        << " method: " << req.method() << " body: " << req.body();

    // ManagedObjectStore instance:
    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }

    store->ClearEventStore();
    asyncResp->res.jsonValue = store->GetEventsToJSON();
}

void ManagedObjectStoreHttp::requestGetGoogleManagedObjectStoreMetrics(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    if (!redfish::setUpRedfishRoute(app, req, asyncResp))
    {
        return;
    }

    asyncResp->res.jsonValue =
        managedStore::GetManagedObjectStore()->GetManagedObjectsMetrics(
            managedStore::clockNow());
}

void ManagedObjectStoreHttp::requestGetGoogleTimetrace(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    (void)app;
    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> GoogleTimetrace:" << " method: " << req.method()
        << " target: " << req.target() << " body: " << req.body();

    // ManagedObjectStore instance:
    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }

    nlohmann::json google;
    google["@odata.id"] =
        "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/GoogleTimetrace";
    google["@odata.type"] = "#GoogleTimetrace.v1_0_0.GoogleTimetrace";

    google["Actions"]["#GoogleTimetrace.Clear"] = {
        {"target",
         "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/GoogleTimetrace/Actions/GoogleTimetrace.Clear"}};

    // timeTrace
    const auto& timeTrace = store->getTimeTrace();
    google["time_trace_size"] = timeTrace.size();
    google["timetrace"] = timeTrace;

    // always keep this one as the last item:
    // final object:
    asyncResp->res.jsonValue = google;
}

void ManagedObjectStoreHttp::handleGoogleTimetraceClearPost(
    App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    (void)app;
    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> GoogleTimetraceClear:" << " method: " << req.method()
        << " target: " << req.target() << " body: " << req.body();

    // ManagedObjectStore instance:
    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }

    store->clearTimeTrace();
}

void ManagedObjectStoreHttp::handleGoogleTakeSnapShot(
    [[maybe_unused]] App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> GoogleTakeSnapShot:" << " method: " << req.method()
        << " target: " << req.target() << " body: " << req.body();

    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }
    if (store->serialize())
    {
        asyncResp->res.jsonValue["ok"] = true;
    }
    else
    {
        asyncResp->res.jsonValue["err"] = "Error making snapshot";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
    }
}

void ManagedObjectStoreHttp::handleGoogleLoadSnapShot(
    [[maybe_unused]] App& app, const crow::Request& req,
    const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
{
    BMCWEB_LOG_STATEFUL_DEBUG
        << "=> GoogleLoadSnapShot:" << " method: " << req.method()
        << " target: " << req.target() << " body: " << req.body();

    auto *store = managedStore::GetManagedObjectStore();
    if (store == nullptr)
    {
        asyncResp->res.jsonValue["err"] = "managed object store is null";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
        return;
    }
    if (store->deserialize())
    {
        asyncResp->res.jsonValue["ok"] = true;
    }
    else
    {
        asyncResp->res.jsonValue["err"] = "Error loading snapshot";
        BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                  << asyncResp->res.jsonValue.dump();
    }
}

void requestRoutesManagedStore(App& app)
{
    // a few exports for debugging:
    BMCWEB_ROUTE(app, "/debug/malloc_stats")
        .methods(boost::beast::http::verb::get)(
            []([[maybe_unused]] const crow::Request& req,
               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        asyncResp->res.jsonValue["ok"] = true;
        malloc_stats();
    });

    // a few exports for debugging:
    BMCWEB_ROUTE(app, "/debug/managed_store")
        // .privileges(redfish::privileges::postManager)
        .methods(boost::beast::http::verb::get)(
            [](const crow::Request& req,
               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::requestRoutesManagedStoreDebug(req, asyncResp);
    });

    // flush the managed objects:
    BMCWEB_ROUTE(app, "/debug/managed_store/clear")
        .methods(boost::beast::http::verb::post)(
            [](const crow::Request& req,
               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::requestRoutesManagedStorePostFlush(req,
                                                                   asyncResp);
    });

    // debug subscriptions
    BMCWEB_ROUTE(app, "/debug/subscriptions")
        .methods(boost::beast::http::verb::get)(
            [](const crow::Request& req,
               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::requestRoutesSubscriptionsDebug(req, asyncResp);
    });

    // debug events
    BMCWEB_ROUTE(app, "/debug/event_store")
        .methods(boost::beast::http::verb::get)(
            [](const crow::Request& req,
               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::requestRoutesEventStoreDebug(req, asyncResp);
    });

    // flush the event store
    BMCWEB_ROUTE(app, "/debug/event_store/clear")
        .methods(boost::beast::http::verb::post)(
            [](const crow::Request& req,
               const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::requestRoutesEventStoreFlush(req, asyncResp);
    });

    // GoogleManagedObjectStoreMetrics:
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/GoogleManagedObjectStoreMetrics")
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::requestGetGoogleManagedObjectStoreMetrics(
            app, req, asyncResp);
    });

    // requests time trace
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/GoogleTimetrace")
        .methods(boost::beast::http::verb::get)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::requestGetGoogleTimetrace(app, req, asyncResp);
    });

    // Clear timetrace:
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/GoogleTimetrace/Actions/GoogleTimetrace.Clear")
        .methods(boost::beast::http::verb::post)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::handleGoogleTimetraceClearPost(app, req,
                                                               asyncResp);
    });

    // take snapshot
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/GoogleSnapShot/Actions/GoogleTakeSnapShot")
        .methods(boost::beast::http::verb::post)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::handleGoogleTakeSnapShot(app, req, asyncResp);
    });

    // load snapshot
    BMCWEB_ROUTE(
        app,
        "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/GoogleSnapShot/Actions/GoogleLoadSnapShot")
        .methods(boost::beast::http::verb::post)(
            [&app](const crow::Request& req,
                   const std::shared_ptr<bmcweb::AsyncResp>& asyncResp) {
        ManagedObjectStoreHttp::handleGoogleLoadSnapShot(app, req, asyncResp);
    });
}

} // namespace managedStore
