#pragma once

#include <cstddef>
#include <cstdint>
#include <string_view>
#include <vector>

#include "adapters/eft/items/catalog/CatalogIndexBuilder.h"
#include "adapters/eft/items/catalog/ItemTemplateReader.h"

struct Il2CppObject;

namespace ta::adapters::eft::items
{
    enum class CatalogPhase
    {
        WaitingForFactory,
        RetryDelay,
        Enumerating,
        Localizing,
        Ready,
        Failed
    };

    struct CatalogRetryPolicy
    {
        int delay_frames = 120;
        int max_attempts = 5;
    };

    class CatalogRebuildJob final
    {
    public:
        explicit CatalogRebuildJob(CatalogRetryPolicy retry_policy = {});

        void update(Il2CppObject* factory);
        void request_reload() noexcept;

        [[nodiscard]] CatalogPhase phase() const noexcept;
        [[nodiscard]] bool loading() const noexcept;
        [[nodiscard]] bool ready() const noexcept;
        [[nodiscard]] std::uint64_t revision() const noexcept;
        [[nodiscard]] const std::vector<ta::features::items::contracts::ItemCatalogEntry>& entries() const noexcept;
        [[nodiscard]] ta::features::items::contracts::ItemCategory category_for(std::string_view id) const;
        [[nodiscard]] int max_stack_for(std::string_view id) const noexcept;

    private:
        static constexpr std::size_t kTemplateBatchSize = 192;
        static constexpr std::size_t kLocalizationBatchSize = 64;

        CatalogRetryPolicy retry_policy_;
        CatalogPhase phase_ = CatalogPhase::WaitingForFactory;
        Il2CppObject* factory_ = nullptr;
        ItemTemplateReader reader_;
        CatalogIndexBuilder builder_;
        std::size_t template_index_ = 0;
        std::size_t localization_index_ = 0;
        std::uint64_t revision_ = 0;
        int retry_frames_ = 0;
        int retry_attempts_ = 0;
        bool reload_requested_ = true;

        void reset_for_factory(Il2CppObject* factory);
        bool begin_rebuild();
        void enumerate_batch();
        void localize_batch();
        void schedule_retry();
        void publish_revision() noexcept;
    };
}
