// WARNING: This file is automatically generated. Any changes will be lost.
#include "twitch-eventsub-ws/messages/metadata.hpp"

#include "twitch-eventsub-ws/chrono.hpp"  // IWYU pragma: keep
#include "twitch-eventsub-ws/detail/errors.hpp"
#include "twitch-eventsub-ws/detail/variant.hpp"  // IWYU pragma: keep

#include <boost/json.hpp>

namespace chatterino::eventsub::lib::messages {

boost::json::result_for<Metadata, boost::json::value>::type tag_invoke(
    boost::json::try_value_to_tag<Metadata> /* tag */,
    const boost::json::value &jvRoot)
{
    if (!jvRoot.is_object())
    {
        EVENTSUB_BAIL_HERE(error::Kind::ExpectedObject);
    }
    const auto &root = jvRoot.get_object();

    const auto *jvmessageID = root.if_contains("message_id");
    if (jvmessageID == nullptr)
    {
        EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
    }

    auto messageID = boost::json::try_value_to<std::string>(*jvmessageID);

    if (messageID.has_error())
    {
        return messageID.error();
    }

    const auto *jvmessageType = root.if_contains("message_type");
    if (jvmessageType == nullptr)
    {
        EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
    }

    auto messageType = boost::json::try_value_to<std::string>(*jvmessageType);

    if (messageType.has_error())
    {
        return messageType.error();
    }

    static_assert(std::is_trivially_copyable_v<std::remove_reference_t<
                      decltype(std::declval<Metadata>().messageTimestamp)>>);
    const auto *jvmessageTimestamp = root.if_contains("message_timestamp");
    if (jvmessageTimestamp == nullptr)
    {
        EVENTSUB_BAIL_HERE(error::Kind::FieldMissing);
    }

    auto messageTimestamp =
        boost::json::try_value_to<std::chrono::system_clock::time_point>(
            *jvmessageTimestamp, AsISO8601());

    if (messageTimestamp.has_error())
    {
        return messageTimestamp.error();
    }

    std::optional<std::string> subscriptionType = std::nullopt;
    const auto *jvsubscriptionType = root.if_contains("subscription_type");
    if (jvsubscriptionType != nullptr && !jvsubscriptionType->is_null())
    {
        auto tsubscriptionType =
            boost::json::try_value_to<std::string>(*jvsubscriptionType);

        if (tsubscriptionType.has_error())
        {
            return tsubscriptionType.error();
        }
        subscriptionType = std::move(tsubscriptionType.value());
    }

    std::optional<std::string> subscriptionVersion = std::nullopt;
    const auto *jvsubscriptionVersion =
        root.if_contains("subscription_version");
    if (jvsubscriptionVersion != nullptr && !jvsubscriptionVersion->is_null())
    {
        auto tsubscriptionVersion =
            boost::json::try_value_to<std::string>(*jvsubscriptionVersion);

        if (tsubscriptionVersion.has_error())
        {
            return tsubscriptionVersion.error();
        }
        subscriptionVersion = std::move(tsubscriptionVersion.value());
    }

    return Metadata{
        .messageID = std::move(messageID.value()),
        .messageType = std::move(messageType.value()),
        .messageTimestamp = messageTimestamp.value(),
        .subscriptionType = std::move(subscriptionType),
        .subscriptionVersion = std::move(subscriptionVersion),
    };
}

}  // namespace chatterino::eventsub::lib::messages
