// WARNING: This file is automatically generated. Any changes will be lost.
#include "twitch-eventsub-ws/payloads/session-welcome.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::payload::session_welcome {

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

    const auto *jvInnerRoot = outerRoot.if_contains("session");
    if (jvInnerRoot == nullptr)
    {
        EVENTSUB_BAIL_HERE(error::Kind::InnerRootMissing);
    }
    if (!jvInnerRoot->is_object())
    {
        EVENTSUB_BAIL_HERE(error::Kind::ExpectedObject);
    }
    const auto &root = jvInnerRoot->get_object();

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

    auto id = boost::json::try_value_to<std::string>(*jvid);

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

    std::optional<std::string> reconnectURL = std::nullopt;
    const auto *jvreconnectURL = root.if_contains("reconnect_url");
    if (jvreconnectURL != nullptr && !jvreconnectURL->is_null())
    {
        auto treconnectURL =
            boost::json::try_value_to<std::string>(*jvreconnectURL);

        if (treconnectURL.has_error())
        {
            return treconnectURL.error();
        }
        reconnectURL = std::move(treconnectURL.value());
    }

    static_assert(
        std::is_trivially_copyable_v<std::remove_reference_t<
            decltype(std::declval<Payload>().keepaliveTimeoutSeconds)>>);
    std::optional<int> keepaliveTimeoutSeconds = std::nullopt;
    const auto *jvkeepaliveTimeoutSeconds =
        root.if_contains("keepalive_timeout_seconds");
    if (jvkeepaliveTimeoutSeconds != nullptr &&
        !jvkeepaliveTimeoutSeconds->is_null())
    {
        auto tkeepaliveTimeoutSeconds =
            boost::json::try_value_to<int>(*jvkeepaliveTimeoutSeconds);

        if (tkeepaliveTimeoutSeconds.has_error())
        {
            return tkeepaliveTimeoutSeconds.error();
        }
        keepaliveTimeoutSeconds = tkeepaliveTimeoutSeconds.value();
    }

    return Payload{
        .id = std::move(id.value()),
        .reconnectURL = std::move(reconnectURL),
        .keepaliveTimeoutSeconds = keepaliveTimeoutSeconds,
    };
}

}  // namespace chatterino::eventsub::lib::payload::session_welcome
