using System.Text.Json; using MealPlanner.Models; namespace MealPlanner.Services; public class TheMealDbClient(HttpClient httpClient) { private const string BaseUrl = "https://www.themealdb.com/api/json/v1/1/"; public async Task GetRandomAsync() { var response = await httpClient.GetAsync($"{BaseUrl}random.php"); if (!response.IsSuccessStatusCode) return null; var json = await response.Content.ReadAsStringAsync(); var meals = ParseMeals(json); return meals.FirstOrDefault(); } public async Task> SearchAsync(string query) { var response = await httpClient.GetAsync($"{BaseUrl}search.php?s={Uri.EscapeDataString(query)}"); if (!response.IsSuccessStatusCode) return []; var json = await response.Content.ReadAsStringAsync(); return ParseMeals(json); } public async Task GetByIdAsync(string id) { var response = await httpClient.GetAsync($"{BaseUrl}lookup.php?i={id}"); if (!response.IsSuccessStatusCode) return null; var json = await response.Content.ReadAsStringAsync(); return ParseMeals(json).FirstOrDefault(); } private static List ParseMeals(string json) { var result = new List(); using var doc = JsonDocument.Parse(json); if (!doc.RootElement.TryGetProperty("meals", out var mealsEl) || mealsEl.ValueKind == JsonValueKind.Null) return result; foreach (var meal in mealsEl.EnumerateArray()) { var recipe = MapMeal(meal); if (recipe is not null) result.Add(recipe); } return result; } private static Recipe? MapMeal(JsonElement meal) { var id = meal.GetStringOrNull("idMeal"); var title = meal.GetStringOrNull("strMeal"); if (id is null || title is null) return null; var recipe = new Recipe { Id = Guid.NewGuid(), ExternalId = id, Title = title, Instructions = meal.GetStringOrNull("strInstructions") ?? "", ImageUrl = meal.GetStringOrNull("strMealThumb"), Source = RecipeSource.TheMealDb, CreatedAt = DateTime.UtcNow, }; // Parse strIngredient1-20 / strMeasure1-20 for (int i = 1; i <= 20; i++) { var name = meal.GetStringOrNull($"strIngredient{i}"); var measure = meal.GetStringOrNull($"strMeasure{i}"); if (string.IsNullOrWhiteSpace(name)) continue; var ingredient = new RecipeIngredient { Id = Guid.NewGuid(), RecipeId = recipe.Id, Name = name.Trim(), }; if (!string.IsNullOrWhiteSpace(measure)) { ParseMeasure(measure.Trim(), out var amount, out var unit); ingredient.Amount = amount; ingredient.Unit = unit; } recipe.Ingredients.Add(ingredient); } GermanTranslator.TranslateRecipe(recipe); return recipe; } private static void ParseMeasure(string measure, out decimal? amount, out string? unit) { amount = null; unit = null; if (string.IsNullOrWhiteSpace(measure)) return; // Try to extract leading number var parts = measure.Trim().Split(' ', 2); if (parts.Length > 0 && decimal.TryParse(parts[0], System.Globalization.NumberStyles.Any, System.Globalization.CultureInfo.InvariantCulture, out var parsed)) { amount = parsed; unit = parts.Length > 1 ? parts[1].Trim() : null; } else { unit = measure; } } } file static class JsonElementExtensions { public static string? GetStringOrNull(this JsonElement el, string propertyName) { if (el.TryGetProperty(propertyName, out var prop) && prop.ValueKind == JsonValueKind.String) { var val = prop.GetString(); return string.IsNullOrWhiteSpace(val) ? null : val; } return null; } }