BareGit
#pragma once

#include <cstdint>
#include <memory>
#include <optional>
#include <string>
#include <vector>

#include <gmock/gmock.h>

#include "data.h"

/// GoogleMock transaction used by service and handler tests.
class DataSourceTransactionMock : public DataSourceTransactionInterface
{
public:
    /// Mock allocation of a never-reused game card number.
    MOCK_METHOD(
        (mw::E<std::uint64_t>),
        allocateGameNumber,
        (const std::string& game_short_name),
        (override));

    /// Mock creation of a game's persistent sequence row.
    MOCK_METHOD(
        (mw::E<void>),
        ensureGameSequence,
        (const std::string& game_short_name),
        (override));

    /// Mock a transaction-consistent game definition read.
    MOCK_METHOD((mw::E<std::optional<GameDefinitionSnapshot>>),
                getGameDefinitionForUpdate,
                (const std::string& short_name), (override));

    /// Mock deletion-relevant game usage.
    MOCK_METHOD((mw::E<GameUsage>), getGameUsage,
                (const std::string& short_name), (override));

    /// Mock game insertion.
    MOCK_METHOD((mw::E<void>), insertGame, (const Game& game), (override));

    /// Mock mutable game metadata replacement.
    MOCK_METHOD((mw::E<bool>), updateGame,
                (const std::string& short_name,
                 const std::string& display_name,
                 const std::string& description,
                 GameVisibility visibility,
                 std::int64_t expected_revision), (override));

    /// Mock game deletion.
    MOCK_METHOD((mw::E<void>), deleteGame,
                (const std::string& short_name), (override));

    /// Mock custom-field insertion.
    MOCK_METHOD((mw::E<std::int64_t>), insertGameField,
                (const GameField& field,
                 const std::vector<GameChoice>& choices), (override));

    /// Mock custom-field replacement.
    MOCK_METHOD((mw::E<void>), updateGameField,
                (std::int64_t field_id, const std::string& label,
                 const std::vector<GameChoice>& choices), (override));

    /// Mock custom-field deletion.
    MOCK_METHOD((mw::E<void>), deleteGameField,
                (std::int64_t field_id), (override));

    /// Mock field usage count.
    MOCK_METHOD((mw::E<std::int64_t>), countFieldUsage,
                (std::int64_t field_id), (override));

    /// Mock exact choice usage count.
    MOCK_METHOD((mw::E<std::int64_t>), countChoiceUsage,
                (std::int64_t field_id, const std::string& value),
                (override));

    /// Mock complete game-field ordering.
    MOCK_METHOD((mw::E<void>), updateGameFieldOrder,
                (const std::string& short_name,
                 const std::vector<std::int64_t>& field_ids), (override));

    /// Mock aggregate definition revision advancement.
    MOCK_METHOD((mw::E<bool>), incrementGameRevision,
                (const std::string& short_name,
                 std::int64_t expected_revision), (override));

    /// Mock transaction-local series ownership validation.
    MOCK_METHOD((mw::E<bool>), seriesBelongToGame,
                (const std::string& short_name,
                 const std::vector<std::int64_t>& series_ids), (override));

    /// Mock the loose-card number collision query.
    MOCK_METHOD(
        (mw::E<bool>),
        looseNumberExists,
        (std::uint32_t number),
        (override));

    /// Mock a user read performed under the transaction lock.
    MOCK_METHOD((mw::E<std::optional<User>>), getUserForUpdate,
                (std::int64_t user_id), (override));

    /// Mock a normalized-email user read under the transaction lock.
    MOCK_METHOD((mw::E<std::optional<User>>), getUserByEmailKeyForUpdate,
                (const std::string& email_key), (override));

    /// Mock a card read performed under the transaction lock.
    MOCK_METHOD(
        (mw::E<std::optional<Card>>),
        getCardForUpdate,
        (std::int64_t card_id),
        (override));

    /// Mock ownership under the transaction lock.
    MOCK_METHOD((mw::E<bool>), userOwnsCardForUpdate,
                (std::int64_t user_id, std::int64_t card_id), (override));

    /// Mock a positive-rarity pool read under the transaction lock.
    MOCK_METHOD((mw::E<std::vector<Card>>), getPoolCardsForUpdate,
                (), (override));

    /// Mock insertion of a newly confirmed user.
    MOCK_METHOD((mw::E<std::int64_t>), insertUser,
                (const User& user), (override));

    /// Mock replacement of a normalized username pair.
    MOCK_METHOD((mw::E<bool>), updateUsername,
                (std::int64_t user_id, const std::string& username,
                 const std::string& username_key), (override));

    /// Mock permanent player promotion.
    MOCK_METHOD((mw::E<bool>), promoteUser,
                (std::int64_t user_id), (override));

    /// Mock atomic authentication-email capacity reservation.
    MOCK_METHOD((mw::E<AuthenticationReservation>),
                reserveAuthenticationEmail,
                (const std::string& email_key, std::int64_t now,
                 bool use_global_quota, std::int64_t utc_day,
                 std::uint32_t daily_limit), (override));

    /// Mock insertion of a pending authentication challenge.
    MOCK_METHOD((mw::E<std::int64_t>), insertAuthenticationChallenge,
                (const std::string& email, const std::string& email_key,
                 const TokenHash& token_hash, std::int64_t created_at,
                 std::int64_t expires_at), (override));

    /// Mock activation of a delivered authentication challenge.
    MOCK_METHOD((mw::E<bool>), markAuthenticationChallengeDelivered,
                (std::int64_t challenge_id, std::int64_t delivered_at),
                (override));

    /// Mock removal of a failed authentication challenge.
    MOCK_METHOD((mw::E<void>), deleteAuthenticationChallenge,
                (std::int64_t challenge_id), (override));

    /// Mock conditional authentication challenge consumption.
    MOCK_METHOD((mw::E<std::optional<AuthenticationChallenge>>),
                consumeAuthenticationChallenge,
                (const TokenHash& token_hash, std::int64_t now), (override));

    /// Mock invalidation of an email identity's other challenges.
    MOCK_METHOD((mw::E<void>), invalidateAuthenticationChallenges,
                (const std::string& email_key,
                 std::int64_t except_challenge_id, std::int64_t now),
                (override));

    /// Mock insertion of a non-sliding session.
    MOCK_METHOD((mw::E<std::int64_t>), insertSession,
                (std::int64_t user_id, const TokenHash& token_hash,
                 const std::string& csrf_token, std::int64_t created_at,
                 std::int64_t expires_at), (override));

    /// Mock deletion of a session digest.
    MOCK_METHOD((mw::E<void>), deleteSession,
                (const TokenHash& token_hash), (override));

    /// Mock persistence of lazily refreshed pull state.
    MOCK_METHOD((mw::E<void>), updatePullState,
                (std::int64_t user_id, std::uint32_t stored_pulls,
                 std::int64_t refresh_day), (override));

    /// Mock insertion or increment of one collection holding.
    MOCK_METHOD((mw::E<std::int64_t>), incrementHolding,
                (std::int64_t user_id, std::int64_t card_id), (override));

    /// Mock insertion of a card and its dynamic dependent rows.
    MOCK_METHOD(
        (mw::E<std::int64_t>),
        insertCard,
        (const Card& card,
         const std::vector<GameFieldValue>& field_values,
         const std::vector<std::int64_t>& series_ids),
        (override));

    /// Mock replacement of a card and its dependent rows.
    MOCK_METHOD(
        (mw::E<void>),
        updateCard,
        (const Card& card,
         const std::vector<GameFieldValue>& field_values,
         const std::vector<std::int64_t>& series_ids),
        (override));

    /// Mock deletion of a card and its dependent rows.
    MOCK_METHOD(
        (mw::E<void>),
        deleteCard,
        (std::int64_t card_id),
        (override));

    /// Mock insertion of a series.
    MOCK_METHOD(
        (mw::E<std::int64_t>),
        insertSeries,
        (const Series& series),
        (override));

    /// Mock replacement of a series.
    MOCK_METHOD(
        (mw::E<void>),
        updateSeries,
        (const Series& series),
        (override));

    /// Mock deletion of a series and its memberships.
    MOCK_METHOD(
        (mw::E<void>),
        deleteSeries,
        (std::int64_t series_id),
        (override));

    /// Mock transaction commit.
    MOCK_METHOD((mw::E<void>), commit, (), (override));
};

/// GoogleMock data source used by service and handler tests.
class DataSourceMock : public DataSourceInterface
{
public:
    /// Mock retrieval of the stored schema version.
    MOCK_METHOD(
        (mw::E<std::int64_t>),
        getSchemaVersion,
        (),
        (const, override));

    /// Mock creation of schema version 1.
    MOCK_METHOD(
        (mw::E<void>),
        migrateSchema0To1,
        (),
        (override));

    /// Mock creation of a mutation transaction.
    MOCK_METHOD(
        (mw::E<std::unique_ptr<DataSourceTransactionInterface>>),
        beginTransaction,
        (),
        (override));

    /// Mock retrieval of all cards.
    MOCK_METHOD(
        (mw::E<std::vector<Card>>),
        getCards,
        (GameContentScope scope),
        (const, override));

    /// Mock retrieval of one creator's authored cards.
    MOCK_METHOD((mw::E<std::vector<Card>>), getCardsByCreator,
                (std::int64_t creator_user_id, GameContentScope scope),
                (const, override));

    /// Mock retrieval of the current positive-rarity pool.
    MOCK_METHOD((mw::E<std::vector<Card>>), getPoolCards,
                (), (const, override));

    /// Mock retrieval of a card by identity.
    MOCK_METHOD(
        (mw::E<std::optional<Card>>),
        getCard,
        (const CardIdentity& identity, GameContentScope scope),
        (const, override));

    /// Mock retrieval of all database-defined games.
    MOCK_METHOD((mw::E<std::vector<Game>>), getGames,
                (GameContentScope scope), (const, override));

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

    /// Mock retrieval of a card's definition and custom values.
    MOCK_METHOD((mw::E<std::optional<CardGameFields>>),
                getCardFieldValues, (std::int64_t card_id,
                                     GameContentScope scope),
                (const, override));

    /// Mock retrieval of a user by internal identity.
    MOCK_METHOD((mw::E<std::optional<User>>), getUser,
                (std::int64_t user_id), (const, override));

    /// Mock retrieval of a user by normalized immutable email.
    MOCK_METHOD((mw::E<std::optional<User>>), getUserByEmailKey,
                (const std::string& email_key), (const, override));

    /// Mock retrieval of all administrator-visible users.
    MOCK_METHOD((mw::E<std::vector<User>>), getUsers,
                (), (const, override));

    /// Mock retrieval of a valid joined session.
    MOCK_METHOD((mw::E<std::optional<SessionContext>>), getSession,
                (const TokenHash& token_hash, std::int64_t now),
                (const, override));

    /// Mock read-only authentication challenge validation.
    MOCK_METHOD((mw::E<std::optional<AuthenticationChallenge>>),
                getAuthenticationChallenge,
                (const TokenHash& token_hash, std::int64_t now),
                (const, override));

    /// Mock retrieval of one user's distinct collection.
    MOCK_METHOD((mw::E<std::vector<CollectionEntry>>), getCollection,
                (std::int64_t user_id, GameContentScope scope),
                (const, override));

    /// Mock a persisted card-ownership query.
    MOCK_METHOD((mw::E<bool>), userOwnsCard,
                (std::int64_t user_id, std::int64_t card_id),
                (const, override));

    /// Mock immutable administrator reconciliation.
    MOCK_METHOD((mw::E<User>), reconcileAdministrator,
                (const std::string& email, const std::string& email_key,
                 std::int64_t created_at, std::int64_t pull_refresh_day),
                (override));

    /// Mock best-effort authentication cleanup.
    MOCK_METHOD((mw::E<void>), cleanupAuthentication,
                (std::int64_t now), (override));

    /// Mock retrieval of all series.
    MOCK_METHOD(
        (mw::E<std::vector<Series>>),
        getSeries,
        (GameContentScope scope),
        (const, override));

    /// Mock retrieval of one series by internal ID.
    MOCK_METHOD(
        (mw::E<std::optional<Series>>),
        getSeries,
        (std::int64_t series_id, GameContentScope scope),
        (const, override));

    /// Mock retrieval of a card's series memberships.
    MOCK_METHOD(
        (mw::E<std::vector<std::int64_t>>),
        getCardSeries,
        (std::int64_t card_id),
        (const, override));

    /// Mock mutation of the stored schema version.
    MOCK_METHOD(
        (mw::E<void>),
        setSchemaVersion,
        (std::int64_t version),
        (override));
};