#include "managed_store_http.hpp"

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

#include <nlohmann/json.hpp>

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

namespace managedStore
{

// Max number of PQ Entries that should be exported for debug.
constexpr size_t kPQExportLimit = 20000;

class ManagedObjectStoreHttp
{
  public:
    // static only class, extension/friend to ManagedObjectStore
    ManagedObjectStoreHttp() = delete;
    ~ManagedObjectStoreHttp() = delete;

    static void requestRoutesManagedStoreDebug(
        App& app, const crow::Request& req,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
    {
        (void)app;

        // 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::managedObjectStore;
        if (!store)
        {
            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:
        const auto& objects = store->getManagedObjects();
        auto jsonObjKeysArray = nlohmann::json::array();
        auto jsonObjects = nlohmann::json();
        for (const auto& iter : objects)
        {
            jsonObjKeysArray.push_back(iter.first);
            jsonObjects[iter.first] = iter.second.toJson();
        }
        asyncResp->res.jsonValue["managed_objects"] = jsonObjects;
        asyncResp->res.jsonValue["managed_objects_keys"] = jsonObjKeysArray;

        // Export pq entries:
        auto jsonObjPqArray = nlohmann::json::array();
        ManagedStorePriorityQueue pq = store->getPriorityQueue();
        size_t entries = 0;
        while (!pq.empty() && entries++ < kPQExportLimit)
        {
            const auto& entry = pq.top();
            jsonObjPqArray.push_back(entry.managedStoreKey.toString());
            pq.pop();
        }
        asyncResp->res.jsonValue["managed_objects_pq_entries"] = jsonObjPqArray;

        // Export sizes for all containers in managedStore:
        asyncResp->res.jsonValue["managed_objects_keys_size"] = objects.size();
        asyncResp->res.jsonValue["managed_objects_pq_size"] =
            store->getPriorityQueue().size();

        // 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;
    }

    static void requestRoutesManagedStorePostFlush(
        App& app, const crow::Request& req,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
    {
        (void)app;

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

        // ManagedObjectStore instance:
        auto store = managedStore::managedObjectStore;
        if (!store)
        {
            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_keys_size"] =
            store->getManagedObjects().size();
        asyncResp->res.jsonValue["managed_objects_pq_size"] =
            store->getPriorityQueue().size();

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

    static void requestGetGoogleManagedObjectStoreMetrics(
        App& app, const crow::Request& req,
        const std::shared_ptr<bmcweb::AsyncResp>& asyncResp)
    {
        (void)app;

        BMCWEB_LOG_STATEFUL_DEBUG << "=> GoogleManagedObjectStoreMetrics:"
                                  << " method: " << req.method()
                                  << " target: " << req.target()
                                  << " body: " << req.body();

        // ManagedObjectStore instance:
        auto store = managedStore::managedObjectStore;
        if (!store)
        {
            asyncResp->res.jsonValue["err"] = "managed object store is null";
            BMCWEB_LOG_STATEFUL_ERROR << "=> ERROR: "
                                      << asyncResp->res.jsonValue.dump();
            return;
        }
        const int64_t kNumBuckets = 20;
        const int64_t kBucketSize = 1000;
        nlohmann::json managedObjectsAgeHistograms = nlohmann::json::array();
        for (size_t i = 0; i < kNumBuckets; i++)
        {
            nlohmann::json bucket;
            bucket["Start"] = i * kBucketSize;
            bucket["Count"] = 0;
            managedObjectsAgeHistograms.push_back(bucket);
        }

        const auto now = clockNow();
        nlohmann::json managedObjects = nlohmann::json::array();
        int64_t maxObjectAgeMs = 0;
        int64_t maxLastServedAgeMs = 0;
        int64_t countLastServed = 0;
        uint64_t sumTotalObjectRefreshes = 0;
        uint64_t sumTotalObjectRefreshScheduled = 0;
        uint64_t sumTotalObjectUsed = 0;

        int keyIndex = 0;
        for (const auto& iter : store->getManagedObjects())
        {
            const auto& key = iter.first;
            const auto& value = iter.second;

            nlohmann::json obj;
            obj["@odata.id"] =
                "/redfish/v1/Managers/bmc/ManagerDiagnosticData/Oem/Google/GoogleManagedObjectStoreMetrics#/ManagedObjects/" +
                std::to_string(keyIndex);
            obj["@odata.type"] =
                "#GoogleManagedObjectMetrics.v1_0_0.GoogleManagedObjectMetrics";

            // Split the key:
            std::string serviceName, objectPath, interface, property;
            KeyType::fromKey(key, serviceName, objectPath, interface, property);

            obj["Id"] = keyIndex;
            obj["ServiceName"] = serviceName;
            obj["ObjectPath"] = objectPath;
            obj["Interface"] = interface;
            obj["Property"] = property;
            obj["Age"] = clockSinceMilliseconds(value.lastRefreshAt, now);
            obj["RefreshCountDone"] = value.numRefreshesDone;
            obj["RefreshCountScheduled"] = value.numRefreshesScheduled;
            obj["NumTimesUsed"] = value.numTimesUsed;

            keyIndex++;

            // sum up the counts:
            sumTotalObjectRefreshes += value.numRefreshesDone;
            sumTotalObjectRefreshScheduled += value.numRefreshesScheduled;
            sumTotalObjectUsed += value.numTimesUsed;

            nlohmann::json lastUsedAgesObj = nlohmann::json::array();
            if (value.lastUsedAges)
            {
                std::for_each(
                    value.lastUsedAges->begin(), value.lastUsedAges->end(),
                    [&](const std::chrono::steady_clock::duration& dur) {
                    const int64_t lastUsedDurationMs =
                        clockDurationMilliseconds(dur);
                    // report the last served ages:
                    lastUsedAgesObj.push_back(lastUsedDurationMs);
                    // total count:
                    countLastServed += 1;
                    // track the max:
                    maxLastServedAgeMs =
                        std::max(maxLastServedAgeMs, lastUsedDurationMs);
                    });
            }
            obj["AgeLastServed"] = lastUsedAgesObj;

            // object age histogram:
            const int64_t objectAgeMs =
                clockSinceMilliseconds(value.lastRefreshAt, now);
            if (objectAgeMs >= 0)
            {
                int64_t bucketIndex =
                    std::min(objectAgeMs / kBucketSize, kNumBuckets);
                if (bucketIndex >= 0)
                {
                    // last buckets catches all:
                    if (bucketIndex >= kNumBuckets)
                        bucketIndex = (kNumBuckets - 1);
                    const auto i = static_cast<size_t>(bucketIndex);
                    auto count =
                        managedObjectsAgeHistograms[i]["Count"]
                            .get_ref<nlohmann::json::number_integer_t&>();
                    managedObjectsAgeHistograms[i]["Count"] = count + 1;
                }
                // max age:
                maxObjectAgeMs = std::max(maxObjectAgeMs, objectAgeMs);
            }
            managedObjects.push_back(obj);
        }

        // complying with:
        // https://critique.corp.google.com/cl/546939035

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

        // Age Buckets:
        google["ManagedObjectsAgeHistograms"]["AgeBuckets"] =
            managedObjectsAgeHistograms;
        // Age Max:
        google["ManagedObjectsAgeHistograms"]["AgeMax"] = maxObjectAgeMs;

        // Last Served Count:
        google["ManagedObjectsAgeHistograms"]["LastServedCount"] =
            countLastServed;
        google["ManagedObjectsAgeHistograms"]["LastServedMax"] =
            maxLastServedAgeMs;

        // Total num of refreshes:
        google["NumRefreshesDone"] = sumTotalObjectRefreshes;
        google["NumRefreshesScheduled"] = sumTotalObjectRefreshScheduled;

        // Total num used:
        google["NumTimesUsed"] = sumTotalObjectUsed;

        // ManagedStore counters from managedStoreTracker
        const ManagedStoreTracker& storeTracker = store->getStoreTracker();
        google["NumGetManagedObjects"] = storeTracker.countGetManagedObjects;
        google["NumGetManagedObjectsCacheMiss"] =
            storeTracker.countGetManagedObjectsCacheMiss;
        google["NumGetManagedObjectsCacheHit"] =
            storeTracker.countGetManagedObjectsCacheHit;
        google["NumGetManagedObjectsCacheMissMaxAge"] =
            storeTracker.countGetManagedObjectsCacheMissMaxAge;

        // Export max pending and the threshold:
        google["PendingResponsesMax"] =
            storeTracker.countMaxPendingDbusResponses;
        google["PendingResponsesThreshold"] =
            storeTracker.countThresholdPendingResponses;

        // objects: (will probably remove from none debug builds)
        google["ManagedObjects"] = managedObjects;
        // final object:
        asyncResp->res.jsonValue = google;
    }
};

void requestRoutesManagedStore(App& app)
{
    // TODO: manage who gets to trigger these (permissions):
    // TODO: perhaps only for debug builds? or runtime flag enabled?
    // TODO: at least integrate with the existing redfish permissions scheme:
    // `.privileges({{"Login"}})`

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

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

} // namespace managedStore