// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: Copyright OpenBMC Authors
#pragma once

#include "event_service_store.hpp"
#include "logging.hpp"
#include "ossl_random.hpp"
#include "sessions.hpp"
// NOLINTNEXTLINE(misc-include-cleaner)
#include "utility.hpp"

#include <boost/beast/core/file_base.hpp>
#include <boost/beast/core/file_posix.hpp>
#include <boost/beast/http/fields.hpp>
#include <nlohmann/json.hpp>

#include <chrono>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include <memory>
#include <optional>
#include <string>
#include <system_error>
#include <utility>

namespace persistent_data
{

class ConfigFile
{
    uint64_t jsonRevision = 1;

  public:
    // todo(ed) should read this from a fixed location somewhere, not CWD
    static constexpr const char* filename = "bmcweb_persistent_data.json";

    ConfigFile()
    {
        readData();
    }

    ~ConfigFile()
    {
        // Make sure we aren't writing stale sessions
        persistent_data::SessionStore::getInstance().applySessionTimeouts();
        if (persistent_data::SessionStore::getInstance().needsWrite())
        {
            writeData();
        }
    }

    ConfigFile(const ConfigFile&) = delete;
    ConfigFile(ConfigFile&&) = delete;
    ConfigFile& operator=(const ConfigFile&) = delete;
    ConfigFile& operator=(ConfigFile&&) = delete;

    // TODO(ed) this should really use protobuf, or some other serialization
    // library, but adding another dependency is somewhat outside the scope of
    // this application for the moment
    void readData()
    {
        std::ifstream persistentFile(filename);
        uint64_t fileRevision = 0;
        if (persistentFile.is_open())
        {
            // call with exceptions disabled
            auto data = nlohmann::json::parse(persistentFile, nullptr, false);
            if (data.is_discarded())
            {
                BMCWEB_LOG_ERROR("Error parsing persistent data in json file.");
            }
            else
            {
                const nlohmann::json::object_t* obj =
                    data.get_ptr<nlohmann::json::object_t*>();
                if (obj == nullptr)
                {
                    return;
                }
                for (const auto& item : *obj)
                {
                    if (item.first == "revision")
                    {
                        fileRevision = 0;

                        const uint64_t* uintPtr =
                            item.second.get_ptr<const uint64_t*>();
                        if (uintPtr == nullptr)
                        {
                            BMCWEB_LOG_ERROR("Failed to read revision flag");
                        }
                        else
                        {
                            fileRevision = *uintPtr;
                        }
                    }
                    else if (item.first == "system_uuid")
                    {
                        const std::string* jSystemUuid =
                            item.second.get_ptr<const std::string*>();
                        if (jSystemUuid != nullptr)
                        {
                            systemUuid = *jSystemUuid;
                        }
                    }
                    else if (item.first == "service_identification")
                    {
                        const std::string* jServiceIdentification =
                            item.second.get_ptr<const std::string*>();
                        if (jServiceIdentification != nullptr)
                        {
                            serviceIdentification = *jServiceIdentification;
                        }
                    }
                    else if (item.first == "auth_config")
                    {
                        const nlohmann::json::object_t* jObj =
                            item.second
                                .get_ptr<const nlohmann::json::object_t*>();
                        if (jObj == nullptr)
                        {
                            continue;
                        }
                        SessionStore::getInstance()
                            .getAuthMethodsConfig()
                            .fromJson(*jObj);
                    }
                    else if (item.first == "sessions")
                    {
                        for (const auto& elem : item.second)
                        {
                            const nlohmann::json::object_t* jObj =
                                elem.get_ptr<const nlohmann::json::object_t*>();
                            if (jObj == nullptr)
                            {
                                continue;
                            }
                            std::shared_ptr<UserSession> newSession =
                                UserSession::fromJson(*jObj);

                            if (newSession == nullptr)
                            {
                                BMCWEB_LOG_ERROR("Problem reading session "
                                                 "from persistent store");
                                continue;
                            }

                            BMCWEB_LOG_DEBUG("Restored session: {} {} {}",
                                             newSession->csrfToken,
                                             newSession->uniqueId,
                                             newSession->sessionToken);
                            SessionStore::getInstance().authTokens.emplace(
                                newSession->sessionToken, newSession);
                        }
                    }
                    else if (item.first == "timeout")
                    {
                        const int64_t* jTimeout =
                            item.second.get_ptr<const int64_t*>();
                        if (jTimeout == nullptr)
                        {
                            BMCWEB_LOG_DEBUG(
                                "Problem reading session timeout value");
                            continue;
                        }
                        std::chrono::seconds sessionTimeoutInseconds(*jTimeout);
                        BMCWEB_LOG_DEBUG("Restored Session Timeout: {}",
                                         sessionTimeoutInseconds.count());
                        SessionStore::getInstance().updateSessionTimeout(
                            sessionTimeoutInseconds);
                    }
                    else if (item.first == "eventservice_config")
                    {
                        const nlohmann::json::object_t* esobj =
                            item.second
                                .get_ptr<const nlohmann::json::object_t*>();
                        if (esobj == nullptr)
                        {
                            BMCWEB_LOG_DEBUG(
                                "Problem reading EventService value");
                            continue;
                        }

                        EventServiceStore::getInstance()
                            .getEventServiceConfig()
                            .fromJson(*esobj);
                    }
                    else if (item.first == "subscriptions")
                    {
                        for (const auto& elem : item.second)
                        {
                            const nlohmann::json::object_t* subobj =
                                elem.get_ptr<const nlohmann::json::object_t*>();
                            if (subobj == nullptr)
                            {
                                continue;
                            }

                            std::optional<UserSubscription> newSub =
                                UserSubscription::fromJson(*subobj);

                            if (!newSub)
                            {
                                BMCWEB_LOG_ERROR(
                                    "Problem reading subscription from persistent store");
                                continue;
                            }

                            std::string id = newSub->id;
                            BMCWEB_LOG_DEBUG("Restored subscription: {} {}", id,
                                             newSub->customText);

                            EventServiceStore::getInstance()
                                .subscriptionsConfigMap.emplace(
                                    id, std::make_shared<UserSubscription>(
                                            std::move(*newSub)));
                        }
                    }
                    else
                    {
                        // Do nothing in the case of extra fields.  We may have
                        // cases where fields are added in the future, and we
                        // want to at least attempt to gracefully support
                        // downgrades in that case, even if we don't officially
                        // support it
                    }
                }
            }
        }
        bool needWrite = false;

        if (systemUuid.empty())
        {
            systemUuid = bmcweb::getRandomUUID();
            needWrite = true;
        }
        if (fileRevision < jsonRevision)
        {
            needWrite = true;
        }
        // write revision changes or system uuid changes immediately
        if (needWrite)
        {
            writeData();
        }
    }

    void writeData()
    {
        std::filesystem::path path(filename);
        path = path.parent_path();
        if (!path.empty())
        {
            std::error_code ecDir;
            std::filesystem::create_directories(path, ecDir);
            if (ecDir)
            {
                BMCWEB_LOG_CRITICAL("Can't create persistent folders {}",
                                    ecDir.message());
                return;
            }
        }
        boost::beast::file_posix persistentFile;
        boost::system::error_code ec;
        persistentFile.open(filename, boost::beast::file_mode::write, ec);
        if (ec)
        {
            BMCWEB_LOG_CRITICAL("Unable to store persistent data to file {}",
                                ec.message());
            return;
        }

        // set the permission of the file to 640
        std::filesystem::perms permission =
            std::filesystem::perms::owner_read |
            std::filesystem::perms::owner_write |
            std::filesystem::perms::group_read;
        std::filesystem::permissions(filename, permission, ec);
        if (ec)
        {
            BMCWEB_LOG_CRITICAL("Failed to set filesystem permissions {}",
                                ec.message());
            return;
        }
        const AuthConfigMethods& c =
            SessionStore::getInstance().getAuthMethodsConfig();
        const auto& eventServiceConfig =
            EventServiceStore::getInstance().getEventServiceConfig();
        nlohmann::json::object_t data;
        nlohmann::json& authConfig = data["auth_config"];

        authConfig["XToken"] = c.xtoken;
        authConfig["Cookie"] = c.cookie;
        authConfig["SessionToken"] = c.sessionToken;
        authConfig["BasicAuth"] = c.basic;
        authConfig["TLS"] = c.tls;
        authConfig["TLSStrict"] = c.tlsStrict;
        authConfig["MTLSCommonNameParseMode"] =
            static_cast<int>(c.mTLSCommonNameParsingMode);

        nlohmann::json& eventserviceConfig = data["eventservice_config"];
        eventserviceConfig["ServiceEnabled"] = eventServiceConfig.enabled;
        eventserviceConfig["DeliveryRetryAttempts"] =
            eventServiceConfig.retryAttempts;
        eventserviceConfig["DeliveryRetryIntervalSeconds"] =
            eventServiceConfig.retryTimeoutInterval;

        data["system_uuid"] = systemUuid;
        data["service_identification"] = serviceIdentification;
        data["revision"] = jsonRevision;
        data["timeout"] = SessionStore::getInstance().getTimeoutInSeconds();

        nlohmann::json& sessions = data["sessions"];
        sessions = nlohmann::json::array();
        for (const auto& p : SessionStore::getInstance().authTokens)
        {
            if (p.second->sessionType != persistent_data::SessionType::Basic &&
                p.second->sessionType !=
                    persistent_data::SessionType::MutualTLS)
            {
                nlohmann::json::object_t session;
                session["unique_id"] = p.second->uniqueId;
                session["session_token"] = p.second->sessionToken;
                session["username"] = p.second->username;
                session["csrf_token"] = p.second->csrfToken;
                session["client_ip"] = p.second->clientIp;
                const std::optional<std::string>& clientId = p.second->clientId;
                if (clientId)
                {
                    session["client_id"] = *clientId;
                }
                sessions.emplace_back(std::move(session));
            }
        }
        nlohmann::json& subscriptions = data["subscriptions"];
        subscriptions = nlohmann::json::array();
        for (const auto& it :
             EventServiceStore::getInstance().subscriptionsConfigMap)
        {
            if (it.second == nullptr)
            {
                continue;
            }
            const UserSubscription& subValue = *it.second;
            if (subValue.subscriptionType == "SSE")
            {
                BMCWEB_LOG_DEBUG("The subscription type is SSE, so skipping.");
                continue;
            }
            nlohmann::json::object_t headers;
            for (const boost::beast::http::fields::value_type& header :
                 subValue.httpHeaders)
            {
                // Note, these are technically copies because nlohmann doesn't
                // support key lookup by std::string_view.  At least the
                // following code can use move
                // https://github.com/nlohmann/json/issues/1529
                std::string name(header.name_string());
                headers[std::move(name)] = header.value();
            }

            nlohmann::json::object_t subscription;

            subscription["Id"] = subValue.id;
            subscription["Context"] = subValue.customText;
            subscription["DeliveryRetryPolicy"] = subValue.retryPolicy;
            subscription["SendHeartbeat"] = subValue.sendHeartbeat;
            subscription["HeartbeatIntervalMinutes"] =
                subValue.hbIntervalMinutes;
            subscription["Destination"] = subValue.destinationUrl;
            subscription["EventFormatType"] = subValue.eventFormatType;
            subscription["HttpHeaders"] = std::move(headers);
            subscription["MessageIds"] = subValue.registryMsgIds;
            subscription["Protocol"] = subValue.protocol;
            subscription["RegistryPrefixes"] = subValue.registryPrefixes;
            subscription["OriginResources"] = subValue.originResources;
            subscription["ResourceTypes"] = subValue.resourceTypes;
            subscription["SubscriptionType"] = subValue.subscriptionType;
            subscription["MetricReportDefinitions"] =
                subValue.metricReportDefinitions;
            subscription["VerifyCertificate"] = subValue.verifyCertificate;

            subscriptions.emplace_back(std::move(subscription));
        }
        std::string out = nlohmann::json(data).dump(
            -1, ' ', true, nlohmann::json::error_handler_t::replace);
        persistentFile.write(out.data(), out.size(), ec);
        if (ec)
        {
            BMCWEB_LOG_ERROR("Failed to write file {}", ec.message());
        }
    }

    std::string systemUuid;
    std::string serviceIdentification;
};

inline ConfigFile& getConfig()
{
    static ConfigFile f;
    return f;
}

} // namespace persistent_data
