using System.Text.Json; using Kochstube.Models; namespace Kochstube.Services; public class RezeptService { private readonly string _rezeptPath; private List? _cache; private DateTime _lastLoad; public RezeptService(IConfiguration config) { _rezeptPath = config["RezeptPath"] ?? Path.Combine(Directory.GetCurrentDirectory(), "..", "..", "rezepte"); } public List GetAll() { // Reload if older than 10 seconds (good enough for dev) if (_cache == null || DateTime.UtcNow - _lastLoad > TimeSpan.FromSeconds(10)) { _cache = LoadFromDisk(); _lastLoad = DateTime.UtcNow; } return _cache; } public Rezept? GetById(string id) => GetAll().FirstOrDefault(r => r.Id == id); public List GetAllTags() => GetAll().SelectMany(r => r.Tags).Distinct().OrderBy(t => t).ToList(); public List GetAllKategorien() => GetAll().Select(r => r.Kategorie).Distinct().OrderBy(k => k).ToList(); public List Search(string? query, string? tag, string? kategorie) { var results = GetAll().AsEnumerable(); if (!string.IsNullOrWhiteSpace(query)) { var q = query.ToLowerInvariant(); results = results.Where(r => r.Titel.Contains(q, StringComparison.OrdinalIgnoreCase) || r.Beschreibung.Contains(q, StringComparison.OrdinalIgnoreCase) || r.Zutaten.Any(z => z.Name.Contains(q, StringComparison.OrdinalIgnoreCase))); } if (!string.IsNullOrWhiteSpace(tag)) results = results.Where(r => r.Tags.Contains(tag, StringComparer.OrdinalIgnoreCase)); if (!string.IsNullOrWhiteSpace(kategorie)) results = results.Where(r => r.Kategorie.Equals(kategorie, StringComparison.OrdinalIgnoreCase)); return results.ToList(); } private List LoadFromDisk() { var dir = Path.GetFullPath(_rezeptPath); if (!Directory.Exists(dir)) return []; var rezepte = new List(); foreach (var file in Directory.GetFiles(dir, "*.json")) { try { var json = File.ReadAllText(file); var r = JsonSerializer.Deserialize(json); if (r != null) rezepte.Add(r); } catch { /* skip broken files */ } } return rezepte.OrderByDescending(r => r.Erstellt ?? "").ThenBy(r => r.Titel).ToList(); } }