#pragma once

#include <cstdint>
#include <memory>
#include <optional>
#include <vector>

#include "adapters/eft/items/catalog/ItemTemplateCatalogService.h"
#include "adapters/eft/items/wishlist/WishlistService.h"
#include "adapters/eft/runtime/EftGameContext.h"
#include "features/items/dependencies/IItemGateway.h"
#include "foundation/concurrency/CoalescingCommandSlot.h"
#include "foundation/concurrency/SharedSnapshotPublisher.h"

namespace ta::adapters::eft::items
{
class EftItemGateway final : public ta::features::items::dependencies::IItemGateway
{
public:
    EftItemGateway(ta::adapters::eft::runtime::EftGameContext& context,
                   ta::adapters::eft::items::WishlistService& wishlist_service,
                   ta::adapters::eft::items::ItemTemplateCatalogService& runtime_catalog);
    void application_tick(const ta::features::items::contracts::ItemSettings& settings) override;
    void game_tick(const ta::features::items::contracts::ItemSettings& settings,
                   std::vector<ta::features::items::contracts::ItemSelectorCommand> selector_commands,
                   std::optional<ta::features::items::contracts::ItemActionCommand> action) override;
    void reset_session() noexcept override;
    [[nodiscard]] std::shared_ptr<const ta::features::items::contracts::ItemCatalogSnapshot> catalog() const noexcept override;
    [[nodiscard]] bool in_raid() const noexcept override;

private:
    struct ActiveCreateBatch
    {
        ta::features::items::contracts::ItemCreateRequest request{};
        int remaining = 0;
        int stacks_created = 0;
    };

    void process_selector_commands(std::vector<ta::features::items::contracts::ItemSelectorCommand> commands);
    void refresh_selector_catalog();
    void queue_action(const ta::features::items::contracts::ItemSettings& settings,
                      ta::features::items::contracts::ItemActionCommand command);
    [[nodiscard]] ta::features::items::contracts::ItemCreateRequest build_create_request(
        const ta::features::items::contracts::ItemSettings& settings,
        ta::features::items::contracts::PendingAction action,
        std::uint64_t trace_id) const;
    void dispatch_item_create_request(ta::adapters::il2cpp::Il2CppObjectInstance game_world_instance,
                                      ta::adapters::il2cpp::Il2CppObjectInstance main_player);

    ta::adapters::eft::runtime::EftGameContext& context_;
    ta::foundation::CoalescingCommandSlot<ta::features::items::contracts::ItemCreateRequest> commands_;
    ta::foundation::SharedSnapshotPublisher<ta::features::items::contracts::ItemCatalogSnapshot> catalog_snapshot_;
    ta::adapters::eft::items::ItemTemplateCatalogService& runtime_catalog_;
    ta::adapters::eft::items::WishlistService& wishlist_service_;
    std::uint64_t wishlist_revision_ = 0;
    std::uint64_t catalog_revision_ = 0;
    bool selector_active_ = false;
    bool reload_requested_ = false;
    int refresh_counter_ = 0;
    std::optional<ActiveCreateBatch> active_create_batch_;
};
}
