// FileDummy Sample C++ File
// Template-based container with RAII and STL usage.

#include <iostream>
#include <vector>
#include <string>
#include <memory>
#include <algorithm>
#include <optional>
#include <unordered_map>

namespace sample {

enum class Role { Admin, User, Guest };

struct User {
    int id;
    std::string name;
    std::string email;
    Role role;

    User(int id, std::string name, std::string email, Role role = Role::User)
        : id(id), name(std::move(name)), email(std::move(email)), role(role) {}

    friend std::ostream& operator<<(std::ostream& os, const User& u) {
        return os << "User{" << u.id << ", " << u.name << ", " << u.email << "}";
    }
};

// ── Template repository ──────────────────────
template <typename T>
class Repository {
public:
    using IdType = int;

    void add(T item) {
        items_[item.id] = std::move(item);
    }

    std::optional<std::reference_wrapper<const T>> find(IdType id) const {
        auto it = items_.find(id);
        if (it == items_.end()) return std::nullopt;
        return std::cref(it->second);
    }

    std::vector<std::reference_wrapper<const T>> all() const {
        std::vector<std::reference_wrapper<const T>> result;
        for (const auto& [_, item] : items_) {
            result.emplace_back(std::cref(item));
        }
        return result;
    }

    bool remove(IdType id) {
        return items_.erase(id) > 0;
    }

    size_t size() const { return items_.size(); }

private:
    std::unordered_map<IdType, T> items_;
};

} // namespace sample

// ── Main ─────────────────────────────────────
int main() {
    using namespace sample;
    Repository<User> repo;

    repo.add(User{1, "Alice", "alice@example.com", Role::Admin});
    repo.add(User{2, "Bob", "bob@example.com", Role::User});

    std::cout << "Total users: " << repo.size() << "\n";
    for (const auto& user : repo.all()) {
        std::cout << "  " << user.get() << "\n";
    }

    if (auto found = repo.find(1)) {
        std::cout << "Found: " << found->get() << "\n";
    }
    return 0;
}
