using Microsoft.EntityFrameworkCore; using MoneyMap.Data; using MoneyMap.Models; namespace MoneyMap.Services; /// /// Service for card management including retrieval, validation, and deletion. /// public interface ICardService { /// /// Gets a card by ID with optional related data. /// Task GetCardByIdAsync(int id, bool includeRelated = false); /// /// Gets all cards with transaction statistics. /// Task> GetAllCardsWithStatsAsync(); /// /// Checks if a card can be deleted (no transactions exist). /// Task CanDeleteCardAsync(int id); /// /// Deletes a card if it has no associated transactions. /// Task DeleteCardAsync(int id); } public class CardService : ICardService { private readonly MoneyMapContext _db; public CardService(MoneyMapContext db) { _db = db; } public async Task GetCardByIdAsync(int id, bool includeRelated = false) { var query = _db.Cards.AsQueryable(); if (includeRelated) { query = query .Include(c => c.Account) .Include(c => c.Transactions); } return await query.FirstOrDefaultAsync(c => c.Id == id); } public async Task> GetAllCardsWithStatsAsync() { // Single query with projection to avoid N+1 return await _db.Cards .Include(c => c.Account) .OrderBy(c => c.Owner) .ThenBy(c => c.Last4) .Select(c => new CardWithStats { Card = c, TransactionCount = c.Transactions.Count }) .ToListAsync(); } public async Task CanDeleteCardAsync(int id) { var card = await _db.Cards.FindAsync(id); if (card == null) return new DeleteValidationResult { CanDelete = false, Reason = "Card not found." }; var transactionCount = await _db.Transactions.CountAsync(t => t.CardId == id); if (transactionCount > 0) return new DeleteValidationResult { CanDelete = false, Reason = $"Cannot delete card. It has {transactionCount} transaction(s) associated with it." }; return new DeleteValidationResult { CanDelete = true }; } public async Task DeleteCardAsync(int id) { var validation = await CanDeleteCardAsync(id); if (!validation.CanDelete) { return new DeleteResult { Success = false, Message = validation.Reason ?? "Cannot delete card." }; } var card = await _db.Cards.FindAsync(id); if (card == null) { return new DeleteResult { Success = false, Message = "Card not found." }; } _db.Cards.Remove(card); await _db.SaveChangesAsync(); return new DeleteResult { Success = true, Message = "Card deleted successfully." }; } }