using Microsoft.EntityFrameworkCore; using BudgetApp.Data; namespace BudgetApp.Services; public class CategoryService(ApplicationDbContext db) { private readonly ApplicationDbContext _db = db; private static readonly (string Name, string Icon)[] DefaultCategories = [ ("Groceries", "🛒"), ("Rent / Mortgage", "🏠"), ("Utilities", "💡"), ("Transport", "🚗"), ("Eating Out", "🍽️"), ("Entertainment", "🎬"), ("Health", "🏥"), ("Insurance", "🛡️"), ("Salary", "💰"), ("Savings", "🏦"), ("Subscriptions", "📱"), ("Shopping", "🛍️"), ("Education", "📚"), ("Travel", "✈️"), ("Gifts", "🎁"), ("Loan", "🏧"), ("Credit Card", "💳"), ("Childcare", "👶") ]; public async Task> GetCategoriesAsync(string userId) { return await _db.Categories .Where(c => c.UserId == userId) .OrderBy(c => c.Name) .ToListAsync(); } public async Task EnsureDefaultCategoriesAsync(string userId) { var existing = await _db.Categories .Where(c => c.UserId == userId) .ToListAsync(); if (existing.Count == 0) { var defaults = DefaultCategories.Select(d => new Category { Name = d.Name, Icon = d.Icon, IsDefault = true, UserId = userId }); _db.Categories.AddRange(defaults); await _db.SaveChangesAsync(); return; } // Backfill icons and IsDefault on existing default categories var defaultLookup = DefaultCategories.ToDictionary(d => d.Name, d => d.Icon); bool updated = false; foreach (var category in existing) { if (string.IsNullOrEmpty(category.Icon) && defaultLookup.TryGetValue(category.Name, out var icon)) { category.Icon = icon; updated = true; } if (!category.IsDefault && defaultLookup.ContainsKey(category.Name)) { category.IsDefault = true; updated = true; } } if (updated) { await _db.SaveChangesAsync(); } } public async Task CreateCategoryAsync(Category category) { _db.Categories.Add(category); await _db.SaveChangesAsync(); } public async Task UpdateCategoryAsync(int id, string userId, string name, string icon) { var category = await _db.Categories .FirstOrDefaultAsync(c => c.Id == id && c.UserId == userId); if (category is not null) { if (category.IsDefault) return; category.Name = name; category.Icon = icon; await _db.SaveChangesAsync(); } } public async Task DeleteCategoryAsync(int id, string userId) { var category = await _db.Categories .FirstOrDefaultAsync(c => c.Id == id && c.UserId == userId); if (category is not null) { if (category.IsDefault) return; _db.Categories.Remove(category); await _db.SaveChangesAsync(); } } }