using SVSim.Database.Enums; namespace SVSim.Database.Repositories.Viewer; /// /// Lightweight profile shape used by chat surfaces (guild_chat, gathering_chat). /// Fields match the ChatUserDto wire shape. /// public record ChatUserProfile( string Name, long EmblemId, string CountryCode, int Rank, int DegreeId); public interface IViewerRepository { Task GetViewerBySocialConnection(SocialAccountType accountType, ulong socialId); Task GetViewerWithSocials(long id); Task GetViewerByShortUdid(long shortUdid); Task GetViewerByUdid(Guid udid); Task RegisterViewer(string displayName, SocialAccountType socialType, ulong socialAccountIdentifier, ulong? shortUdid = null); Task RegisterAnonymousViewer(Guid udid); Task LinkSteamToViewer(long viewerId, ulong steamId); /// /// Merges an anonymous viewer (just created by /tool/signup on a fresh UDID) /// into a target viewer that the Steam ticket resolved to. Transfers the anonymous /// viewer's UDID to the target, then deletes the anonymous viewer. /// Task MergeAnonymousViewerInto(long anonymousViewerId, long targetViewerId); /// /// Focused load for building a battle-node MatchContext: viewer + Info + Info's /// equipped Emblem/Degree nav refs. Read-only (AsNoTracking). Returns null if the viewer /// doesn't exist. /// Task LoadForMatchContextAsync(long viewerId); /// Sets Viewer.GuildId to . No-op if the viewer does not exist. Task SetGuildIdAsync(long viewerId, int guildId, CancellationToken ct = default); /// Clears Viewer.GuildId to null. No-op if the viewer does not exist. Task ClearGuildIdAsync(long viewerId, CancellationToken ct = default); /// /// Batch-loads DisplayName for a set of viewer ids. Returns a dictionary keyed by viewer id; /// ids with no matching row are absent from the result. Read-only (AsNoTracking). /// Task> LoadDisplayNamesAsync(IReadOnlyCollection viewerIds, CancellationToken ct = default); /// /// Batch-loads the fields for a set of viewer ids. Used by chat /// surfaces (guild_chat, gathering_chat) to populate users[] without a direct DB context /// in the controller. Ids with no matching row are absent from the result. Read-only (AsNoTracking). /// Task> LoadChatProfilesAsync(IReadOnlyCollection viewerIds, CancellationToken ct = default); }