#pragma once
#include "logging.hpp"

#include <boost/beast/http/fields.hpp>
#include <boost/container/flat_map.hpp>
#include <boost/url/parse.hpp>
#include <boost/url/url.hpp>
#include <nlohmann/json.hpp>

#include <memory>
#include <string>
#include <vector>

namespace persistent_data
{

struct UserSubscription
{
    // Represents a Redfish EventDestination instance
    std::string id;
    boost::urls::url destinationUrl;
    std::string protocol;
    bool verifyCertificate = true;
    std::string retryPolicy;
    std::string customText;
    std::string eventFormatType;
    std::string subscriptionType;
    std::vector<std::string> registryMsgIds;
    std::vector<std::string> registryPrefixes;
    std::vector<std::string> resourceTypes;
    boost::beast::http::fields httpHeaders;
    std::vector<std::string> metricReportDefinitions;
    std::vector<std::string> originResources;

    static std::optional<UserSubscription> fromJson(
        const nlohmann::json::object_t& j, const bool loadFromOldConfig = false)
    {
        UserSubscription subvalue;
        for (const auto& element : j)
        {
            if (element.first == "Id")
            {
                const std::string* value =
                    element.second.get_ptr<const std::string*>();
                if (value == nullptr)
                {
                    continue;
                }
                subvalue.id = *value;
            }
            else if (element.first == "Destination")
            {
                const std::string* value =
                    element.second.get_ptr<const std::string*>();
                if (value == nullptr)
                {
                    continue;
                }
                boost::system::result<boost::urls::url> url =
                    boost::urls::parse_absolute_uri(*value);
                if (!url)
                {
                    continue;
                }
                subvalue.destinationUrl = std::move(*url);
            }
            else if (element.first == "Protocol")
            {
                const std::string* value =
                    element.second.get_ptr<const std::string*>();
                if (value == nullptr)
                {
                    continue;
                }
                subvalue.protocol = *value;
            }
            else if (element.first == "VerifyCertificate")
            {
                const bool* value = element.second.get_ptr<const bool*>();
                if (value == nullptr)
                {
                    continue;
                }
                subvalue.verifyCertificate = *value;
            }
            else if (element.first == "DeliveryRetryPolicy")
            {
                const std::string* value =
                    element.second.get_ptr<const std::string*>();
                if (value == nullptr)
                {
                    continue;
                }
                subvalue.retryPolicy = *value;
            }
            else if (element.first == "Context")
            {
                const std::string* value =
                    element.second.get_ptr<const std::string*>();
                if (value == nullptr)
                {
                    continue;
                }
                subvalue.customText = *value;
            }
            else if (element.first == "EventFormatType")
            {
                const std::string* value =
                    element.second.get_ptr<const std::string*>();
                if (value == nullptr)
                {
                    continue;
                }
                subvalue.eventFormatType = *value;
            }
            else if (element.first == "SubscriptionType")
            {
                const std::string* value =
                    element.second.get_ptr<const std::string*>();
                if (value == nullptr)
                {
                    continue;
                }
                subvalue.subscriptionType = *value;
            }
            else if (element.first == "MessageIds")
            {
                const nlohmann::json::array_t* obj =
                    element.second.get_ptr<const nlohmann::json::array_t*>();
                if (obj == nullptr)
                {
                    continue;
                }
                for (const auto& val : *obj)
                {
                    const std::string* value =
                        val.get_ptr<const std::string*>();
                    if (value == nullptr)
                    {
                        continue;
                    }
                    subvalue.registryMsgIds.emplace_back(*value);
                }
            }
            else if (element.first == "RegistryPrefixes")
            {
                const nlohmann::json::array_t* obj =
                    element.second.get_ptr<const nlohmann::json::array_t*>();
                if (obj == nullptr)
                {
                    continue;
                }
                for (const auto& val : *obj)
                {
                    const std::string* value =
                        val.get_ptr<const std::string*>();
                    if (value == nullptr)
                    {
                        continue;
                    }
                    subvalue.registryPrefixes.emplace_back(*value);
                }
            }
            else if (element.first == "ResourceTypes")
            {
                const nlohmann::json::array_t* obj =
                    element.second.get_ptr<const nlohmann::json::array_t*>();
                if (obj == nullptr)
                {
                    continue;
                }
                for (const auto& val : *obj)
                {
                    const std::string* value =
                        val.get_ptr<const std::string*>();
                    if (value == nullptr)
                    {
                        continue;
                    }
                    subvalue.resourceTypes.emplace_back(*value);
                }
            }
            else if (element.first == "HttpHeaders")
            {
                const nlohmann::json::object_t* obj =
                    element.second.get_ptr<const nlohmann::json::object_t*>();
                if (obj == nullptr)
                {
                    continue;
                }
                for (const auto& val : *obj)
                {
                    const std::string* value =
                        val.second.get_ptr<const std::string*>();
                    if (value == nullptr)
                    {
                        BMCWEB_LOG_ERROR("Failed to parse value for key{}",
                                         val.first);
                        continue;
                    }
                    subvalue.httpHeaders.set(val.first, *value);
                }
            }
            else if (element.first == "MetricReportDefinitions")
            {
                const nlohmann::json::array_t* obj =
                    element.second.get_ptr<const nlohmann::json::array_t*>();
                if (obj == nullptr)
                {
                    continue;
                }
                for (const auto& val : *obj)
                {
                    const std::string* value =
                        val.get_ptr<const std::string*>();
                    if (value == nullptr)
                    {
                        continue;
                    }
                    subvalue.metricReportDefinitions.emplace_back(*value);
                }
            }
            else if (element.first == "OriginResources")
            {
                const nlohmann::json::array_t* obj =
                    element.second.get_ptr<const nlohmann::json::array_t*>();
                if (obj == nullptr)
                {
                    continue;
                }
                for (const auto& val : *obj)
                {
                    const std::string* value =
                        val.get_ptr<const std::string*>();
                    if (value == nullptr)
                    {
                        continue;
                    }
                    subvalue.originResources.emplace_back(*value);
                }
            }
            else
            {
                BMCWEB_LOG_ERROR(
                    "Got unexpected property reading persistent file: {}",
                    element.first);
                continue;
            }
        }

        if ((subvalue.id.empty() && !loadFromOldConfig) ||
            subvalue.destinationUrl.empty() || subvalue.protocol.empty() ||
            subvalue.retryPolicy.empty() || subvalue.eventFormatType.empty() ||
            subvalue.subscriptionType.empty())
        {
            BMCWEB_LOG_ERROR("Subscription missing required field "
                             "information, refusing to restore");
            return std::nullopt;
        }

        return subvalue;
    }
};

struct EventServiceConfig
{
    bool enabled = true;
    uint32_t retryAttempts = 3;
    uint32_t retryTimeoutInterval = 30;

    void fromJson(const nlohmann::json::object_t& j)
    {
        for (const auto& element : j)
        {
            if (element.first == "ServiceEnabled")
            {
                const bool* value = element.second.get_ptr<const bool*>();
                if (value == nullptr)
                {
                    continue;
                }
                enabled = *value;
            }
            else if (element.first == "DeliveryRetryAttempts")
            {
                const uint64_t* value =
                    element.second.get_ptr<const uint64_t*>();
                if ((value == nullptr) ||
                    (*value > std::numeric_limits<uint32_t>::max()))
                {
                    continue;
                }
                retryAttempts = static_cast<uint32_t>(*value);
            }
            else if (element.first == "DeliveryRetryIntervalSeconds")
            {
                const uint64_t* value =
                    element.second.get_ptr<const uint64_t*>();
                if ((value == nullptr) ||
                    (*value > std::numeric_limits<uint32_t>::max()))
                {
                    continue;
                }
                retryTimeoutInterval = static_cast<uint32_t>(*value);
            }
        }
    }
};

class EventServiceStore
{
  public:
    boost::container::flat_map<std::string, std::shared_ptr<UserSubscription>>
        subscriptionsConfigMap;
    EventServiceConfig eventServiceConfig;

    static EventServiceStore& getInstance()
    {
        static EventServiceStore eventServiceStore;
        return eventServiceStore;
    }

    EventServiceConfig& getEventServiceConfig()
    {
        return eventServiceConfig;
    }
};

} // namespace persistent_data
