#ifndef BRAIN_EPOCH_FILTER_HPP_
#define BRAIN_EPOCH_FILTER_HPP_

#include <unordered_set>
#include <string>
#include <atomic>
#include <mutex>
#include <vector>

namespace brain
{

/**
 * @brief Maintains an epoch counter and allowed skill set to filter incoming BT feedback.
 *
 * Used to ignore stale or unrelated feedback messages. Only feedback matching the current epoch and
 * belonging to the declared skill subset (if non-empty) is accepted.
 *
 * Thread-safety:
 *  - reset_epoch acquires a mutex to update the skill set and epoch atomically.
 *  - accept acquires the mutex only if a non-empty skill name needs membership validation.
 */
class EpochSkillFilter
{
public:
  /**
   * @brief Set a new epoch and replace the allowed skill filter set.
   * @param new_epoch Epoch identifier.
   * @param skills List of allowed skill names (cleared if empty).
   */
  void reset_epoch(uint64_t new_epoch, const std::vector<std::string> & skills)
  {
    std::lock_guard<std::mutex> lk(mtx_);
    epoch_.store(new_epoch, std::memory_order_relaxed);
    skills_.clear();
    for (auto & s : skills) {skills_.insert(s);}
  }
  /**
   * @brief Get the current epoch.
   */
  uint64_t epoch() const {return epoch_.load(std::memory_order_relaxed);}
  /**
   * @brief Determine if feedback should be considered.
   * @param feedback_epoch Epoch in the feedback message.
   * @param skill Skill name associated with feedback (may be empty to bypass name filtering).
   * @param bt_pending Whether a BT execution is still pending.
   * @return true if epoch matches, bt_pending is true, and skill (if provided) is allowed.
   */
  bool accept(uint64_t feedback_epoch, const std::string & skill, bool bt_pending) const
  {
    if (!bt_pending) {return false;}
    if (feedback_epoch != epoch_.load(std::memory_order_relaxed)) {return false;}
    if (!skill.empty()) {
      std::lock_guard<std::mutex> lk(mtx_);
      if (skills_.find(skill) == skills_.end()) {return false;}
    }
    return true;
  }

private:
  mutable std::mutex mtx_;                 ///< Guards skill set
  std::atomic<uint64_t> epoch_{0};         ///< Current epoch
  std::unordered_set<std::string> skills_; ///< Allowed skills for current epoch
};

} // namespace brain

#endif // BRAIN_EPOCH_FILTER_HPP_
