#pragma once
#include <cstdint>
#include <mw/crypto.hpp>
#include <mw/error.hpp>
#include "card_pool.h"
#include "clock.h"
#include "data.h"
/// Result of one successful atomic card pull.
struct PullResult
{
/// Selected current card.
Card card;
/// User's quantity after the award.
std::int64_t quantity;
};
/// Own lazy pull accrual and atomic collection awards.
class CollectionService
{
public:
/// Construct the service over injected time, randomness, and persistence.
CollectionService(
DataSourceInterface& data_source,
ClockInterface& clock,
mw::CryptoInterface& crypto,
std::uint32_t maximum_accumulated_pulls);
/// Refresh and persist one user's available pulls.
mw::E<User> refresh(std::int64_t user_id);
/// Consume one pull and increment the selected holding atomically.
mw::E<PullResult> pull(std::int64_t user_id);
private:
/// Calculate availability and nondecreasing refresh day.
std::pair<std::uint32_t, std::int64_t> effectivePullState(
const User& user, std::int64_t current_day) const;
DataSourceInterface& data_source_;
ClockInterface& clock_;
mw::CryptoInterface& crypto_;
std::uint32_t maximum_accumulated_pulls_;
CardPoolService card_pool_;
};