BareGit
#pragma once

#include <cstdint>
#include <string>
#include <unordered_map>
#include <variant>
#include <vector>

/// Supported storage and form behavior for a custom game field.
enum class GameFieldType
{
    INTEGER,
    STRING,
    CHOICE
};

/// Application visibility assigned to a database-defined game.
enum class GameVisibility
{
    PUBLIC = 0,
    INTERNAL = 1
};

/// Visibility boundary for data derived from database-defined games.
enum class GameContentScope
{
    PUBLIC_ONLY,
    INCLUDE_INTERNAL
};

/// One database-defined game.
struct Game
{
    /// Permanent lowercase public card-ID prefix.
    std::string short_name;

    /// Human-readable game name.
    std::string display_name;

    /// Markdown game description.
    std::string description;

    /// Application visibility for this game and its derived content.
    GameVisibility visibility;

    /// Aggregate optimistic-concurrency revision.
    std::int64_t revision;
};

/// One allowed value for a choice field.
struct GameChoice
{
    /// Exact stored and displayed choice text.
    std::string value;

    /// Zero-based display position.
    std::int64_t position;
};

/// One ordered custom field belonging to a game.
struct GameField
{
    /// Internal database identity.
    std::int64_t id;

    /// Permanent owning game short name.
    std::string game_short_name;

    /// Permanent key used in submitted form names.
    std::string key;

    /// Human-readable field label.
    std::string label;

    /// Field value type.
    GameFieldType type;

    /// Zero-based display position.
    std::int64_t position;

    /// Ordered allowed values, populated only for choice fields.
    std::vector<GameChoice> choices;
};

/// Consistent owning snapshot of a game and all its field definitions.
struct GameDefinitionSnapshot
{
    /// Database-defined game metadata.
    Game game;

    /// Fields ordered by position and stable identity.
    std::vector<GameField> fields;
};

/// Decoded storage value for one custom field.
struct GameFieldValue
{
    /// Referenced field identity.
    std::int64_t field_id;

    /// Field discriminator retained for database constraint checks.
    GameFieldType type;

    /// Parsed integer or exact string/choice text.
    std::variant<std::int64_t, std::string> value;
};

/// One card's values paired with a consistent owning game definition.
struct CardGameFields
{
    /// Definition used to interpret and present the stored values.
    GameDefinitionSnapshot definition;

    /// Set values ordered by their fields' display positions.
    std::vector<GameFieldValue> values;
};

/// Counts that determine whether a database-defined game can be deleted.
struct GameUsage
{
    /// Cards that use the game.
    std::int64_t card_count;

    /// Series that use the game.
    std::int64_t series_count;

    /// Highest public card number ever allocated for the game.
    std::int64_t last_number;
};

/// Unique custom-field form values keyed by permanent field key.
using SubmittedGameFields =
    std::unordered_map<std::string, std::string>;

/// Dynamic series metadata belonging to one database-defined game.
struct Series
{
    /// Internal SQLite primary key, or zero before insertion.
    std::int64_t id;

    /// Lowercase short name of the owning database-defined game.
    std::string game_short_name;

    /// Series name, unique within its game.
    std::string name;

    /// Markdown series description.
    std::string description;
};