using System.Net.Http.Json; using LehrerApp.Core.Interfaces; using LehrerApp.Core.Models; using LehrerApp.Core.Services; namespace LehrerApp.Sync; /// /// Exportiert einen lesbaren Snapshot der lokalen LiteDB /// und pusht ihn zur API – wo er für die WebApp abrufbar ist. /// /// Wird automatisch nach jedem Sync-Zyklus ausgeführt /// und kann manuell angestoßen werden. /// public class ReadableSnapshotService { private readonly HttpClient _http; private readonly IStudentRepository _students; private readonly IGroupRepository _groups; private readonly IEnrollmentRepository _enrollments; private readonly IExamRepository _exams; private readonly IExamResultRepository _examResults; private readonly IGradeRepository _grades; private readonly IUnitRepository _units; private readonly ILessonRepository _lessons; private readonly IWorkTaskRepository _tasks; private readonly SchoolYearService _schoolYear; private readonly string _deviceId; public event Action? StatusChanged; public ReadableSnapshotService( HttpClient http, IStudentRepository students, IGroupRepository groups, IEnrollmentRepository enrollments, IExamRepository exams, IExamResultRepository examResults, IGradeRepository grades, IUnitRepository units, ILessonRepository lessons, IWorkTaskRepository tasks, SchoolYearService schoolYear, string deviceId) { _http = http; _students = students; _groups = groups; _enrollments = enrollments; _exams = exams; _examResults = examResults; _grades = grades; _units = units; _lessons = lessons; _tasks = tasks; _schoolYear = schoolYear; _deviceId = deviceId; } // ── Export ──────────────────────────────────────────────────────────────── public async Task ExportAndPushAsync( CancellationToken ct = default) { StatusChanged?.Invoke("Snapshot wird erstellt…"); try { var snapshot = BuildSnapshot(); StatusChanged?.Invoke("Snapshot wird übertragen…"); var response = await _http.PostAsJsonAsync( "/api/snapshot/readable", snapshot, ct); if (!response.IsSuccessStatusCode) { StatusChanged?.Invoke( $"Übertragung fehlgeschlagen: {response.StatusCode}"); return false; } StatusChanged?.Invoke( $"Snapshot übertragen – {snapshot.Meta.StudentCount} Schüler, " + $"{snapshot.Meta.GroupCount} Gruppen"); return true; } catch (Exception ex) { StatusChanged?.Invoke($"Fehler: {ex.Message}"); return false; } } // ── Snapshot aufbauen ───────────────────────────────────────────────────── private ReadableSnapshot BuildSnapshot() { var schoolYear = _schoolYear.CurrentSchoolYear(); var groups = _groups.GetBySchoolYear(schoolYear); var groupIds = groups.Select(g => g.Id).ToHashSet(); var students = _students.GetAll(); var enrollments = groups .SelectMany(g => _enrollments.GetByGroupAndYear(g.Id, schoolYear)) .ToList(); var exams = groupIds .SelectMany(gid => _exams.GetByGroup(gid)) .ToList(); var examResults = exams .SelectMany(e => _examResults.GetByExam(e.Id)) .ToList(); var grades = groupIds .SelectMany(gid => _grades.GetByGroup(gid)) .ToList(); var units = groupIds .SelectMany(gid => _units.GetByGroup(gid)) .ToList(); var lessons = units .SelectMany(u => _lessons.GetByUnit(u.Id)) .ToList(); var tasks = _tasks.GetAll() .Where(t => t.Status != WorkTaskStatus.Done) .ToList(); var snapshot = new ReadableSnapshot { SchoolYear = schoolYear, Students = students, Groups = groups, Enrollments = enrollments, Exams = exams, ExamResults = examResults, Grades = grades, Units = units, Lessons = lessons, Tasks = tasks, Meta = new SnapshotMeta { StudentCount = students.Count, GroupCount = groups.Count, ExamCount = exams.Count, ExportedByDevice = _deviceId, OldestData = DateTime.UtcNow.AddYears(-1), // vereinfacht }, }; return snapshot; } }