#pragma once

#include <chrono>
#include <memory>
#include <set>
#include <string>
#include <unordered_map>

#include "features/quests/contracts/IQuestCommands.h"
#include "features/quests/contracts/IQuestQueries.h"
#include "features/quests/dependencies/IQuestGateway.h"
#include "features/quests/QuestDiagnostics.h"
#include "foundation/concurrency/CommandQueue.h"
#include "application/contracts/IGameTick.h"
#include "foundation/concurrency/SharedSnapshotPublisher.h"

namespace ta::features::quests
{
    class QuestFeature final :
        public contracts::IQuestQueries,
        public contracts::IQuestCommands,
        public ta::application::IGameTick
    {
    public:
        explicit QuestFeature(dependencies::IQuestGateway& gateway) noexcept;

        void submit(contracts::QuestCommandBatch batch) override;
        [[nodiscard]] std::shared_ptr<const contracts::QuestListSnapshot> latest_snapshot() const noexcept override;

        void on_game_tick() override;
        void reset_session() noexcept;
        [[nodiscard]] QuestDiagnosticsSnapshot diagnostics_snapshot() const noexcept { return diagnostics_.snapshot(); }

    private:
        dependencies::IQuestGateway& gateway_;
        ta::foundation::CommandQueue<contracts::QuestCommandBatch> commands_;
        contracts::PendingQuestCommands pending_;
        ta::foundation::SharedSnapshotPublisher<contracts::QuestListSnapshot> snapshot_;
        std::unordered_map<std::string, std::uint64_t> complete_trace_ids_;
        std::unordered_map<std::string, std::uint64_t> skip_trace_ids_;
        std::set<std::uint64_t> processing_logged_;
        QuestDiagnostics diagnostics_;
        std::chrono::steady_clock::time_point next_process_at_{};

        [[nodiscard]] bool drain_commands_into_pending();
        [[nodiscard]] bool has_pending_commands() const noexcept;
        void clear_completed(const std::set<std::string>& completed_ids);
    };
}
