namespace SVSim.Database.Repositories.Card;
///
/// Mutating operations on a viewer's card inventory (destruct, create, protect…).
/// Read-only catalog queries live on .
///
public interface ICardInventoryRepository
{
///
/// Validate-then-mutate destruct of owned cards. Atomic: all validation runs before any
/// mutation, and the mutation phase is wrapped in an explicit DB transaction so a mid-flight
/// EF failure rolls back currency + inventory + deck-strip together.
///
/// Authenticated viewer.
/// cardId → num_to_destruct. Empty dict is rejected by the caller.
///
/// with post-state totals on success, or a
/// when validation fails. On error nothing is written.
///
Task DestructCards(long viewerId, IReadOnlyDictionary destructCounts);
///
/// Validate-then-mutate craft of cards from RedEther. Atomic in a transaction; on validation
/// failure nothing is written. Routes Card grants through
/// so the CardCosmeticReward cascade fires for first-time owners.
///
/// cardId → num_to_create. Empty dict is rejected by the caller.
Task CreateCards(long viewerId, IReadOnlyDictionary createCounts);
}
///
/// Either a success payload or an error code. Discriminated by which field is set.
///
public sealed record DestructOutcome(DestructResult? Result, DestructError? Error)
{
public bool IsSuccess => Result is not null;
public static DestructOutcome Ok(DestructResult r) => new(r, null);
public static DestructOutcome Fail(DestructError e) => new(null, e);
}
public sealed record DestructResult(
ulong NewRedEtherTotal,
IReadOnlyDictionary NewOwnedCounts); // cardId → post-destruct Count
public enum DestructError
{
UnknownCard,
NotDestructible,
CardProtected,
InsufficientCards,
}
public sealed record CreateOutcome(CreateResult? Result, CreateError? Error)
{
public bool IsSuccess => Result is not null;
public static CreateOutcome Ok(CreateResult r) => new(r, null);
public static CreateOutcome Fail(CreateError e) => new(null, e);
}
///
/// Outcome of a successful create. is the flattened
/// list returned by
/// — one Card entry per crafted cardId plus any cosmetic-cascade entries.
///
public sealed record CreateResult(
ulong NewRedEtherTotal,
IReadOnlyList Grants);
public enum CreateError
{
UnknownCard,
NotCraftable,
WouldExceedMaxCopies,
InsufficientVials,
}