using Microsoft.EntityFrameworkCore; using RR3CommunityServer.Data; using RR3CommunityServer.Models; namespace RR3CommunityServer.Services; public class SessionService : ISessionService { private readonly RR3DbContext _context; public SessionService(RR3DbContext context) { _context = context; } public async Task CreateSession(string? synergyId = null) { var sessionId = Guid.NewGuid().ToString(); var session = new Session { SessionId = sessionId, SynergyId = synergyId, CreatedAt = DateTime.UtcNow, ExpiresAt = DateTime.UtcNow.AddHours(24) }; _context.Sessions.Add(session); await _context.SaveChangesAsync(); return sessionId; } public async Task ValidateSession(string sessionId) { var session = await _context.Sessions .FirstOrDefaultAsync(s => s.SessionId == sessionId); return session != null && session.ExpiresAt > DateTime.UtcNow; } public async Task GetSynergyIdFromSession(string sessionId) { var session = await _context.Sessions .FirstOrDefaultAsync(s => s.SessionId == sessionId); return session?.SynergyId; } } public class UserService : IUserService { private readonly RR3DbContext _context; public UserService(RR3DbContext context) { _context = context; } public async Task GetOrCreateDeviceId(string? existingDeviceId, string hardwareId) { if (!string.IsNullOrEmpty(existingDeviceId)) { var existing = await _context.Devices .FirstOrDefaultAsync(d => d.DeviceId == existingDeviceId); if (existing != null) { existing.LastSeenAt = DateTime.UtcNow; await _context.SaveChangesAsync(); return existing.DeviceId; } } var deviceId = Guid.NewGuid().ToString(); var device = new Device { DeviceId = deviceId, HardwareId = hardwareId, CreatedAt = DateTime.UtcNow, LastSeenAt = DateTime.UtcNow }; _context.Devices.Add(device); await _context.SaveChangesAsync(); return deviceId; } public async Task ValidateDeviceId(string deviceId) { var device = await _context.Devices .FirstOrDefaultAsync(d => d.DeviceId == deviceId); if (device != null) { device.LastSeenAt = DateTime.UtcNow; await _context.SaveChangesAsync(); return "valid"; } return "invalid"; } public async Task GetOrCreateAnonUid() { return await Task.FromResult(Guid.NewGuid().ToString()); } public async Task GetOrCreateSynergyId(string deviceId) { var user = await _context.Users .FirstOrDefaultAsync(u => u.DeviceId == deviceId); if (user != null) { return user.SynergyId; } var synergyId = $"SYN-{Guid.NewGuid():N}"; user = new User { SynergyId = synergyId, DeviceId = deviceId, CreatedAt = DateTime.UtcNow }; _context.Users.Add(user); await _context.SaveChangesAsync(); return synergyId; } } public class CatalogService : ICatalogService { private readonly RR3DbContext _context; public CatalogService(RR3DbContext context) { _context = context; } public async Task> GetAvailableItems() { var items = await _context.CatalogItems .Where(c => c.Available) .ToListAsync(); return items.Select(e => new Models.CatalogItem { itemId = e.Sku, sku = e.Sku, name = e.Name, description = e.Type, category = e.Type, price = e.Price, currency = "USD" }).ToList(); } public async Task> GetCategories() { var items = await _context.CatalogItems .Where(c => c.Available) .ToListAsync(); var categories = items.GroupBy(i => i.Type) .Select(g => new CatalogCategory { categoryId = g.Key, name = g.Key, itemIds = g.Select(i => i.Sku).ToList() }).ToList(); return categories; } public async Task GetDownloadUrl(string itemId) { return await Task.FromResult($"https://localhost:5001/downloads/{itemId}"); } } public class DrmService : IDrmService { private readonly RR3DbContext _context; public DrmService(RR3DbContext context) { _context = context; } public async Task GenerateNonce() { return await Task.FromResult(Convert.ToBase64String(Guid.NewGuid().ToByteArray())); } public async Task> GetPurchasedItems(string synergyId) { var purchases = await _context.Purchases .Where(p => p.SynergyId == synergyId) .ToListAsync(); return purchases.Select(p => new PurchasedItem { itemId = p.ItemId, sku = p.Sku, orderId = p.OrderId, purchaseTime = new DateTimeOffset(p.PurchaseTime).ToUnixTimeSeconds(), token = p.Token }).ToList(); } public async Task VerifyAndRecordPurchase(string synergyId, PurchaseVerificationRequest request) { // For community server, we accept all purchases var purchase = new Purchase { SynergyId = synergyId, ItemId = request.sku, Sku = request.sku, OrderId = request.orderId, PurchaseTime = DateTime.UtcNow, Token = request.receipt }; _context.Purchases.Add(purchase); await _context.SaveChangesAsync(); return true; } }