using SVSim.Database.Entities.Guild; using SVSim.Database.Models.Config; using SVSim.Database.Repositories.Guild; using SVSim.Database.Services; namespace SVSim.Database.Services.Guild; public sealed class GuildChatService : IGuildChatService { private readonly IGuildMemberRepository _members; private readonly IGuildChatMessageRepository _msgs; private readonly IGameConfigService _cfg; public GuildChatService( IGuildMemberRepository members, IGuildChatMessageRepository msgs, IGameConfigService cfg) { _members = members; _msgs = msgs; _cfg = cfg; } // ── System-event emission ──────────────────────────────────────────────── public async Task EmitSystemEventAsync( int guildId, long actorViewerId, GuildChatMessageType type, string? body = null, CancellationToken ct = default) { var msg = new GuildChatMessage { GuildId = guildId, AuthorViewerId = actorViewerId, MessageType = type, Body = body ?? "", CreatedAt = DateTime.UtcNow, }; await _msgs.AppendAsync(msg, ct); } // ── Window query ───────────────────────────────────────────────────────── public async Task GetWindowAsync( long viewerId, int startMessageId, int direction, int waitIntervalHint, CancellationToken ct = default) { var membership = await _members.GetMembershipAsync(viewerId, ct); if (membership is null) { var idleInterval = _cfg.Get().ChatPollIdleSeconds; return new(Array.Empty(), idleInterval); } const int limit = 50; var msgs = await _msgs.GetWindowAsync(membership.GuildId, startMessageId, direction, limit, ct); var cfg = _cfg.Get(); int wait = msgs.Count == 0 ? cfg.ChatPollIdleSeconds : cfg.ChatPollActiveSeconds; return new(msgs, wait); } // ── Not-yet-implemented stubs ──────────────────────────────────────────── public Task PostTextOrStampAsync(long viewerId, int type, string message, CancellationToken ct = default) => throw new NotImplementedException(); public Task PostDeckAsync(long viewerId, string deckPayloadJson, CancellationToken ct = default) => throw new NotImplementedException(); public Task DeleteDeckAsync(long viewerId, int messageId, CancellationToken ct = default) => throw new NotImplementedException(); public Task PostReplayAsync(long viewerId, string replayPayloadJson, CancellationToken ct = default) => throw new NotImplementedException(); public Task GetReplayDetailAsync(long viewerId, int messageId, CancellationToken ct = default) => throw new NotImplementedException(); public Task GetDeckLogAsync(long viewerId, int messageId, CancellationToken ct = default) => throw new NotImplementedException(); }