using KoogleApp.Entities; using Microsoft.EntityFrameworkCore; using System; using Koogle.Domain.Interfaces; using Microsoft.Extensions.Logging; namespace KoogleApp.Data.Repository { public class InMemoryPlayerRepository : IPlayerRepository { private readonly List _data = new(); private readonly List _playerExpenses = new(); private int _nextId = 1; private readonly SemaphoreSlim _lock = new(1, 1); public InMemoryPlayerRepository() { // Seed-Daten für Entwicklung _data.AddRange(new[] { new Player { Id = _nextId++, Name = "Christian Kauer", //Description = "Beschreibung 1", CreatedAt = DateTime.UtcNow.AddDays(-5) }, new Player { Id = _nextId++, Name = "Michael Thöne", //Description = "Beschreibung 2", CreatedAt = DateTime.UtcNow.AddDays(-3) }, new Player { Id = _nextId++, Name = "Christian Hermann", //Description = "Beschreibung 3", CreatedAt = DateTime.UtcNow.AddDays(-1) }, new Player { Id = _nextId++, Name = "Stefan Meinerzhagen", //Description = "Beschreibung 3", CreatedAt = DateTime.UtcNow.AddDays(-1) } }); _playerExpenses.AddRange([ new PlayerExpense() { Id = 1, PlayerId = _data[0].Id, Name = "Expense 1", CreatedAt = DateTime.UtcNow.AddDays(-1) } ]); } public async Task> GetAllAsync(bool includeExpenses = false) { await _lock.WaitAsync(); try { // Simuliere Datenbanklatenz await Task.Delay(100); return _data.Select(d => new Player { Id = d.Id, Name = d.Name, //Description = d.Description, CreatedAt = d.CreatedAt, ModifiedAt = d.ModifiedAt, ModifiedBy = d.ModifiedBy, Expenses = includeExpenses ? _playerExpenses.Where(p => p.PlayerId == d.Id) .OrderBy(p => p.CreatedAt) .ToList() : new List() }).ToList(); } finally { _lock.Release(); } } public async Task GetByIdAsync(int id, bool includeExpenses = false) { await _lock.WaitAsync(); try { await Task.Delay(50); var item = _data.FirstOrDefault(d => d.Id == id); if (item == null) return null; return new Player { Id = item.Id, Name = item.Name, //Description = item.Description, CreatedAt = item.CreatedAt, ModifiedAt = item.ModifiedAt, ModifiedBy = item.ModifiedBy, Expenses = includeExpenses ? _playerExpenses.Where(p => p.PlayerId == id) .OrderBy(p => p.CreatedAt) .ToList() : new List() }; } finally { _lock.Release(); } } public async Task CreateAsync(Player item) { await _lock.WaitAsync(); try { await Task.Delay(100); item.Id = _nextId++; item.CreatedAt = DateTime.UtcNow; // Positionen IDs setzen foreach (var pos in item.Expenses) { pos.Id = _playerExpenses.Any() ? _playerExpenses.Max(p => p.Id) + 1 : 1; pos.PlayerId = item.Id; _playerExpenses.Add(pos); } _data.Add(item); return item; } finally { _lock.Release(); } } public async Task UpdateAsync(Player item) { await _lock.WaitAsync(); try { await Task.Delay(100); var existing = _data.FirstOrDefault(d => d.Id == item.Id); if (existing == null) throw new KeyNotFoundException($"Item with ID {item.Id} not found"); existing.Name = item.Name; existing.PlayerStatus = item.PlayerStatus; //existing.Description = item.Description; existing.ModifiedAt = DateTime.UtcNow; existing.ModifiedBy = item.ModifiedBy; // Positionen aktualisieren (einfache Strategie: alte löschen, neue hinzufügen) _playerExpenses.RemoveAll(p => p.PlayerId == item.Id); foreach (var pos in item.Expenses) { if (pos.Id == 0) pos.Id = _playerExpenses.Any() ? _playerExpenses.Max(p => p.Id) + 1 : 1; pos.PlayerId = item.Id; _playerExpenses.Add(pos); } existing.Expenses = item.Expenses; return existing; } finally { _lock.Release(); } } public async Task DeleteAsync(int id) { await _lock.WaitAsync(); try { await Task.Delay(50); var item = _data.FirstOrDefault(d => d.Id == id); if (item == null) return false; // Cascade Delete - Positionen auch löschen _playerExpenses.RemoveAll(p => p.PlayerId == id); _data.Remove(item); return true; } finally { _lock.Release(); } } } public class PlayerRepository : IPlayerRepository { private readonly IDbContextFactory _contextFactory; private readonly ILogger _logger; public PlayerRepository( IDbContextFactory contextFactory, ILogger logger) { _contextFactory = contextFactory; _logger = logger; } public async Task> GetAllAsync(bool includeExpenses = false) { try { await using var context = await _contextFactory.CreateDbContextAsync(); return await context.Players .OrderByDescending(d => d.CreatedAt) .ToListAsync(); } catch (Exception ex) { _logger.LogError(ex, "Error loading all data items"); throw; } } public async Task GetByIdAsync(int id, bool includeExpenses = false) { try { await using var context = await _contextFactory.CreateDbContextAsync(); return await context.Players .FirstOrDefaultAsync(d => d.Id == id); } catch (Exception ex) { _logger.LogError(ex, "Error loading data item {Id}", id); throw; } } public async Task CreateAsync(Player item) { try { await using var context = await _contextFactory.CreateDbContextAsync(); item.CreatedAt = DateTime.UtcNow; context.Players.Add(item); await context.SaveChangesAsync(); return item; } catch (Exception ex) { _logger.LogError(ex, "Error creating data item"); throw; } } public async Task UpdateAsync(Player item) { try { await using var context = await _contextFactory.CreateDbContextAsync(); var existing = await context.Players.FindAsync(item.Id); if (existing == null) throw new KeyNotFoundException($"Item with ID {item.Id} not found"); existing.Name = item.Name; existing.PlayerStatus = item.PlayerStatus; //existing.Description = item.Description; existing.ModifiedAt = DateTime.UtcNow; existing.ModifiedBy = item.ModifiedBy; await context.SaveChangesAsync(); return existing; } catch (Exception ex) { _logger.LogError(ex, "Error updating data item {Id}", item.Id); throw; } } public async Task DeleteAsync(int id) { try { await using var context = await _contextFactory.CreateDbContextAsync(); var item = await context.Players.FindAsync(id); if (item == null) return false; context.Players.Remove(item); await context.SaveChangesAsync(); return true; } catch (Exception ex) { _logger.LogError(ex, "Error deleting data item {Id}", id); throw; } } } }