using System.Net; using System.Net.Http.Json; using System.Text.Json; using LehrerApp.Core.Models; namespace LehrerApp.Desktop.Services; public sealed class SchoolWeatherException(string message) : Exception(message); /// Client für das serverseitige Schulstandort-/Wetterprofil. Liest URL und Token je /// Aufruf, damit ein Login oder Serverwechsel in den Einstellungen sofort berücksichtigt wird. public sealed class SchoolWeatherService(HttpClient http, SyncSettingsService syncSettings) { public bool IsAvailable => !string.IsNullOrWhiteSpace(syncSettings.ServerUrl) && syncSettings.IsLoggedIn; public async Task GetLocationAsync(CancellationToken cancellationToken = default) { using var response = await SendAsync(HttpMethod.Get, "/api/school/location", null, cancellationToken); if (response.StatusCode == HttpStatusCode.NotFound) return null; await EnsureSuccessAsync(response); return await response.Content.ReadFromJsonAsync(cancellationToken); } public async Task SaveLocationAsync(SchoolLocationRequest location, CancellationToken cancellationToken = default) { using var response = await SendAsync(HttpMethod.Put, "/api/school/location", location, cancellationToken); await EnsureSuccessAsync(response); return await response.Content.ReadFromJsonAsync(cancellationToken) ?? throw new SchoolWeatherException("Der Server hat keine Standortdaten zurückgegeben."); } public async Task GetWeatherAsync(CancellationToken cancellationToken = default) { using var response = await SendAsync(HttpMethod.Get, "/api/school/weather", null, cancellationToken); if (response.StatusCode == HttpStatusCode.NotFound) return null; await EnsureSuccessAsync(response); return await response.Content.ReadFromJsonAsync(cancellationToken); } private async Task SendAsync(HttpMethod method, string path, object? body, CancellationToken cancellationToken) { if (string.IsNullOrWhiteSpace(syncSettings.ServerUrl) || !syncSettings.IsLoggedIn) throw new SchoolWeatherException("Bitte zuerst im Reiter „Synchronisation“ am Server anmelden."); using var request = new HttpRequestMessage(method, new Uri(new Uri(syncSettings.ServerUrl), path)); var token = syncSettings.GetToken(); if (token is not null) request.Headers.Authorization = new("Bearer", token); if (body is not null) request.Content = JsonContent.Create(body); try { return await http.SendAsync(request, cancellationToken); } catch (HttpRequestException) { throw new SchoolWeatherException("Der LehrerApp-Server ist nicht erreichbar."); } } private static async Task EnsureSuccessAsync(HttpResponseMessage response) { if (response.IsSuccessStatusCode) return; if (response.StatusCode == HttpStatusCode.Unauthorized) throw new SchoolWeatherException("Die Server-Anmeldung ist abgelaufen. Bitte erneut anmelden."); try { using var document = JsonDocument.Parse(await response.Content.ReadAsStringAsync()); if (document.RootElement.TryGetProperty("detail", out var detail) && !string.IsNullOrWhiteSpace(detail.GetString())) throw new SchoolWeatherException(detail.GetString()!); } catch (JsonException) { } throw new SchoolWeatherException("Der Schulstandort konnte nicht gespeichert werden."); } }