namespace LehrerApp.Sync.Models; /// /// Ein einzelnes Ereignis im Event-Log. /// Wird verschlüsselt zum Server übertragen – der Server versteht den Payload nicht. /// public class SyncEvent { public Guid EventId { get; init; } = Guid.NewGuid(); public string DeviceId { get; init; } = ""; public DeviceType DeviceType { get; init; } public DateTime Timestamp { get; init; } = DateTime.UtcNow; public long SequenceNr { get; init; } // monoton steigend pro Gerät public string EntityType { get; init; } = ""; // "Student", "Exam", "Grade" ... public string EntityId { get; init; } = ""; public string Operation { get; init; } = ""; // "Create", "Update", "Delete" public string Payload { get; init; } = ""; // JSON, AES-256 verschlüsselt } /// /// Eintrag im lokalen Konflikt-Log – für UI-Anzeige. /// public class ConflictEntry { public Guid Id { get; init; } = Guid.NewGuid(); public DateTime DetectedAt { get; init; } = DateTime.UtcNow; public SyncEvent LocalEvent { get; init; } = null!; public SyncEvent RemoteEvent { get; init; } = null!; public string Resolution { get; init; } = ""; // "LocalWon", "RemoteWon", "Pending" public bool Reviewed { get; set; } } /// /// Antwort des Servers auf einen Pull-Request. /// public class PullResponse { public List Events { get; init; } = []; public long ServerSequenceNr { get; init; } } /// /// Antwort des Servers auf einen Push-Request. /// public class PushResponse { public bool Success { get; init; } public long ServerSequenceNr { get; init; } public List ConflictingEventIds { get; init; } = []; } public enum DeviceType { Desktop, Companion } /// /// Sync-Status für UI-Anzeige. /// public class SyncStatus { public SyncState State { get; set; } = SyncState.Idle; public DateTime? LastSyncAt { get; set; } public int PendingEvents { get; set; } public int ConflictCount { get; set; } public string? ErrorMessage { get; set; } } public enum SyncState { Idle, Syncing, Error, Offline }