using LehrerApp.Core.Interfaces; using LehrerApp.Core.Models; namespace LehrerApp.Desktop.Tests; // Einfache In-Memory-Fakes der Repository-Schnittstellen, damit ViewModel-Tests ohne echte // LiteDB-Anbindung laufen. Bewusst schlank gehalten: nur was die getesteten ViewModels brauchen. public class FakeStudents(List all) : IStudentRepository { public Student? GetById(Guid id) => all.FirstOrDefault(s => s.Id == id); public List GetAll(bool includeInactive = false) => all; public List GetByGroup(Guid groupId) => all; public void Save(Student student) { } public void Delete(Guid id) { } } public class FakeMemberships(List all) : IGroupMembershipRepository { public List GetByStudent(Guid studentId) => all.Where(m => m.StudentId == studentId).ToList(); public List GetByGroup(Guid groupId) => all.Where(m => m.GroupId == groupId).ToList(); public GroupMembership? GetByStudentAndGroup(Guid studentId, Guid groupId) => all.FirstOrDefault(m => m.StudentId == studentId && m.GroupId == groupId); public void Save(GroupMembership membership) { } public void Delete(Guid id) { } } public class FakeSessions(List all) : IParticipationSessionRepository { public List GetByGroup(Guid groupId) => all.Where(s => s.GroupId == groupId).ToList(); public ParticipationSession? GetById(Guid id) => all.FirstOrDefault(s => s.Id == id); public void Save(ParticipationSession session) { } public void Delete(Guid id) { } } public class FakeEntries : IParticipationRepository { private readonly List _all = []; public void Add(ParticipationEntry e) => _all.Add(e); public List GetBySession(Guid sessionId) => _all.Where(e => e.SessionId == sessionId).ToList(); public List GetByStudent(Guid studentId) => _all.Where(e => e.StudentId == studentId).ToList(); public ParticipationEntry? GetBySessionAndStudent(Guid sessionId, Guid studentId) => _all.FirstOrDefault(e => e.SessionId == sessionId && e.StudentId == studentId); public void Save(ParticipationEntry entry) { _all.RemoveAll(e => e.Id == entry.Id); _all.Add(entry); } public void SaveMany(List entries) { foreach (var e in entries) Save(e); } public void DeleteBySession(Guid sessionId) => _all.RemoveAll(e => e.SessionId == sessionId); } public class FakeAspects : IParticipationAspectRepository { public List GetDefaults() => []; public List GetByGroup(Guid groupId) => []; public void Save(ParticipationAspect aspect) { } public void Delete(Guid id) { } } public class FakeGrades : IGradeRepository { private readonly List _all = []; public void Add(Grade g) => _all.Add(g); public List GetByStudentAndGroup(Guid studentId, Guid groupId) => _all.Where(g => g.StudentId == studentId && g.GroupId == groupId).ToList(); public List GetByGroup(Guid groupId) => _all.Where(g => g.GroupId == groupId).ToList(); public void Save(Grade grade) { _all.RemoveAll(g => g.Id == grade.Id); _all.Add(grade); } public void Delete(Guid id) => _all.RemoveAll(g => g.Id == id); } public class FakeExams(List all) : IExamRepository { public Exam? GetById(Guid id) => all.FirstOrDefault(e => e.Id == id); public List GetByGroup(Guid groupId) => all.Where(e => e.GroupId == groupId).ToList(); public void Save(Exam exam) { } public void Delete(Guid id) { } } public class FakeResults : IExamResultRepository { private readonly List _all = []; // Upsert-Semantik nach ExamId+StudentId, wie der reale unique Index es erzwingt. public void Add(ExamResult r) { _all.RemoveAll(x => x.ExamId == r.ExamId && x.StudentId == r.StudentId); _all.Add(r); } public List GetByExam(Guid examId) => _all.Where(r => r.ExamId == examId).ToList(); public List GetByStudent(Guid studentId) => _all.Where(r => r.StudentId == studentId).ToList(); public ExamResult? GetByExamAndStudent(Guid examId, Guid studentId) => _all.FirstOrDefault(r => r.ExamId == examId && r.StudentId == studentId); public void Save(ExamResult result) { } public void SaveMany(List results) { } } public class FakeGradingKeyTemplates : IGradingKeyTemplateRepository { private readonly List _all = []; public List GetAll() => _all; public List GetByGradingSystem(GradingSystem system) => _all.Where(t => t.GradingSystem == system).ToList(); public GradingKeyTemplate? GetById(Guid id) => _all.FirstOrDefault(t => t.Id == id); public void Save(GradingKeyTemplate template) { _all.RemoveAll(t => t.Id == template.Id); _all.Add(template); } public void Delete(Guid id) => _all.RemoveAll(t => t.Id == id); } public class FakeSchemes : IGradingSchemeRepository { private readonly Dictionary _byGroup = []; private readonly Dictionary _byType = []; public void SetForGroup(Guid groupId, GradingScheme s) => _byGroup[groupId] = s; public void SetDefault(GroupType type, GradingScheme s) => _byType[type] = s; public GradingScheme? GetByGroup(Guid groupId) => _byGroup.GetValueOrDefault(groupId); public GradingScheme? GetDefaultForType(GroupType type) => _byType.GetValueOrDefault(type); public void Save(GradingScheme scheme) { } public void Delete(Guid id) { } } public class FakeGroups(List all) : IGroupRepository { public LearningGroup? GetById(Guid id) => all.FirstOrDefault(g => g.Id == id); public List GetAll(bool includeInactive = false) => all; public List GetBySchoolYear(string schoolYear, bool includeInactive = false) => all; public void Save(LearningGroup group) { } public void Delete(Guid id) { } } public class FakeDocumentation : IDocumentationRepository { private readonly List _all = []; public void Add(Documentation d) => _all.Add(d); public List GetByStudent(Guid studentId) => _all.Where(d => d.StudentId == studentId && !d.IsDeleted).ToList(); public List GetByStudentAndType(Guid studentId, DocumentationType type) => _all.Where(d => d.StudentId == studentId && d.Type == type && !d.IsDeleted).ToList(); public List GetAll() => _all.Where(d => !d.IsDeleted).ToList(); public void Save(Documentation doc) { _all.RemoveAll(d => d.Id == doc.Id); _all.Add(doc); } public void Delete(Guid id) { var d = _all.FirstOrDefault(x => x.Id == id); if (d is not null) d.IsDeleted = true; } public void HardDelete(Guid id) => _all.RemoveAll(d => d.Id == id); } public class FakeAttachmentStorage : IAttachmentStorage { private readonly Dictionary _blobs = []; public string Upload(string fileName, Stream content) { using var ms = new MemoryStream(); content.CopyTo(ms); var id = Guid.NewGuid().ToString("N"); _blobs[id] = ms.ToArray(); return id; } public Stream? OpenRead(string storageId) => _blobs.TryGetValue(storageId, out var b) ? new MemoryStream(b) : null; public void Delete(string storageId) => _blobs.Remove(storageId); } public class FakeUnits : IUnitRepository { private readonly List _all = []; public void Add(Unit u) => _all.Add(u); public Unit? GetById(Guid id) => _all.FirstOrDefault(u => u.Id == id); public List GetByGroup(Guid groupId) => _all.Where(u => u.GroupId == groupId).OrderBy(u => u.StartDate).ToList(); public void Save(Unit unit) { _all.RemoveAll(u => u.Id == unit.Id); _all.Add(unit); } public void Delete(Guid id) => _all.RemoveAll(u => u.Id == id); } public class FakeLessons : ILessonRepository { private readonly List _all = []; public void Add(Lesson l) => _all.Add(l); public List GetByUnit(Guid unitId) => _all.Where(l => l.UnitId == unitId).OrderBy(l => l.Date).ThenBy(l => l.LessonNumber).ToList(); public List GetByGroupAndDate(Guid groupId, DateOnly date) => _all.Where(l => l.GroupId == groupId && l.Date == date).ToList(); public List GetByGroupAndRange(Guid groupId, DateOnly from, DateOnly to) => _all.Where(l => l.GroupId == groupId && l.Date >= from && l.Date <= to).OrderBy(l => l.Date).ToList(); public void Save(Lesson lesson) { _all.RemoveAll(l => l.Id == lesson.Id); _all.Add(lesson); } public void Delete(Guid id) => _all.RemoveAll(l => l.Id == id); } public class FakeSubjects(List all) : ISubjectRepository { public List GetAll() => all; public Subject? GetById(Guid id) => all.FirstOrDefault(s => s.Id == id); public Subject? GetByName(string name) => all.FirstOrDefault(s => s.Name == name); public void Save(Subject subject) { } public void Delete(Guid id) { } } public class FakeCompetencyDomains : ICompetencyDomainRepository { public List GetBySubjectAndGrade(Guid subjectId, int gradeLevel) => []; public CompetencyDomain? GetById(Guid id) => null; public void Save(CompetencyDomain domain) { } public void Delete(Guid id) { } public void DeleteBySubjectAndGrade(Guid subjectId, int gradeLevel) { } } public class FakeShorthandCodes(List all) : IShorthandCodeRepository { public List GetAll() => all; public void Save(ShorthandCode code) { } public void Delete(Guid id) { } } public class FakeAlternativeLessonPaths(List all) : IAlternativeLessonPathRepository { public List GetAll() => all; public AlternativeLessonPath? GetById(Guid id) => all.FirstOrDefault(p => p.Id == id); public void Save(AlternativeLessonPath path) { all.RemoveAll(p => p.Id == path.Id); all.Add(path); } public void Delete(Guid id) => all.RemoveAll(p => p.Id == id); } public class FakeTimetableSlots : ITimetableSlotRepository { private readonly List _all = []; public void Add(TimetableSlot s) => _all.Add(s); public List GetAll() => _all.ToList(); public List GetByGroup(Guid groupId) => _all.Where(s => s.GroupId == groupId).ToList(); public void Save(TimetableSlot slot) { var occupied = _all.FirstOrDefault(s => s.Weekday == slot.Weekday && s.PeriodNumber == slot.PeriodNumber); if (occupied is not null && occupied.Id != slot.Id) throw new InvalidOperationException("Diese Stunde ist bereits belegt."); _all.RemoveAll(s => s.Id == slot.Id); _all.Add(slot); } public void Delete(Guid id) => _all.RemoveAll(s => s.Id == id); } public class FakeSchoolHolidays : ISchoolHolidayRepository { private readonly List _all = []; public void Add(SchoolHoliday h) => _all.Add(h); public List GetAll() => _all.ToList(); public void Save(SchoolHoliday holiday) { _all.RemoveAll(h => h.Id == holiday.Id); _all.Add(holiday); } public void Delete(Guid id) => _all.RemoveAll(h => h.Id == id); } public class FakeSupervisionDuties : ISupervisionDutyRepository { private readonly List _all = []; public void Add(SupervisionDuty d) => _all.Add(d); public List GetAll() => _all.ToList(); public void Save(SupervisionDuty duty) { var occupied = _all.FirstOrDefault(d => d.Weekday == duty.Weekday && d.AfterPeriod == duty.AfterPeriod); if (occupied is not null && occupied.Id != duty.Id) throw new InvalidOperationException("Für diese Pause ist bereits eine Aufsicht eingetragen."); _all.RemoveAll(d => d.Id == duty.Id); _all.Add(duty); } public void Delete(Guid id) => _all.RemoveAll(d => d.Id == id); } public class FakeSubstitutionEntries : ISubstitutionEntryRepository { private readonly List _all = []; public void Add(SubstitutionEntry e) => _all.Add(e); public List GetAll() => _all.ToList(); public List GetByDate(DateOnly date) => _all.Where(e => e.Date == date).ToList(); public void Save(SubstitutionEntry entry) { _all.RemoveAll(e => e.Id == entry.Id); _all.Add(entry); } public void Delete(Guid id) => _all.RemoveAll(e => e.Id == id); } public class FakeReportGrades : IReportGradeRepository { private readonly List _all = []; public int SavedCount { get; private set; } public List GetByGroup(Guid groupId) => _all.Where(r => r.GroupId == groupId).ToList(); public ReportGrade? GetByStudentGroupPeriod(Guid studentId, Guid groupId, string period) => _all.FirstOrDefault(r => r.StudentId == studentId && r.GroupId == groupId && r.Period == period); public void Save(ReportGrade grade) { _all.RemoveAll(r => r.Id == grade.Id); _all.Add(grade); SavedCount++; } public void Delete(Guid id) => _all.RemoveAll(r => r.Id == id); }