BareGit
#pragma once

#include <cstdint>
#include <unordered_map>
#include <vector>

#include "data.h"

/// Deterministic read-only data source for development and focused tests.
class DataSourceFake : public DataSourceInterface
{
public:
    /// Construct an empty fake data source at the latest schema version.
    DataSourceFake() = default;

    /// Construct a fake data source containing the supplied records.
    explicit DataSourceFake(
        std::vector<Card> cards,
        std::vector<Series> series = {},
        std::unordered_map<std::int64_t, std::vector<std::int64_t>>
            card_series = {},
        std::vector<GameDefinitionSnapshot> game_definitions = {},
        std::unordered_map<std::int64_t, std::vector<GameFieldValue>>
            field_values = {});

    /// Return the latest schema version represented by the fake.
    mw::E<std::int64_t> getSchemaVersion() const override;

    /// Reject migration because the fake already has the current schema.
    mw::E<void> migrateSchema0To1() override;

    /// Reject mutation transactions because the fake is read-only.
    mw::E<std::unique_ptr<DataSourceTransactionInterface>>
    beginTransaction() override;

    /// Return all configured cards in insertion order.
    mw::E<std::vector<Card>> getCards(
        GameContentScope scope) const override;

    /// Return configured cards authored by one user.
    mw::E<std::vector<Card>> getCardsByCreator(
        std::int64_t creator_user_id,
        GameContentScope scope) const override;

    /// Return the configured card matching an identity.
    mw::E<std::optional<Card>>
    getCard(
        const CardIdentity& identity,
        GameContentScope scope) const override;

    /// Return configured games ordered by display name and short name.
    mw::E<std::vector<Game>> getGames(
        GameContentScope scope) const override;

    /// Return one configured complete game definition.
    mw::E<std::optional<GameDefinitionSnapshot>> getGameDefinition(
        const std::string& short_name,
        GameContentScope scope) const override;

    /// Return a configured card's game definition and values.
    mw::E<std::optional<CardGameFields>> getCardFieldValues(
        std::int64_t card_id,
        GameContentScope scope) const override;

    /// Return all configured series in insertion order.
    mw::E<std::vector<Series>> getSeries(
        GameContentScope scope) const override;

    /// Return the configured series with an internal ID.
    mw::E<std::optional<Series>>
    getSeries(
        std::int64_t series_id,
        GameContentScope scope) const override;

    /// Return configured series memberships for a card.
    mw::E<std::vector<std::int64_t>>
    getCardSeries(std::int64_t card_id) const override;

protected:
    /// Reject schema mutation because the fake is read-only.
    mw::E<void> setSchemaVersion(std::int64_t version) override;

private:
    bool gameVisible(
        const std::string& short_name,
        GameContentScope scope) const;

    bool cardVisible(const Card& card, GameContentScope scope) const;

    std::vector<Card> cards_;
    std::vector<Series> series_;
    std::unordered_map<std::int64_t, std::vector<std::int64_t>> card_series_;
    std::vector<GameDefinitionSnapshot> game_definitions_;
    std::unordered_map<std::int64_t, std::vector<GameFieldValue>>
        field_values_;
};