using Microsoft.EntityFrameworkCore; using PowderCoating.Application.Interfaces; using PowderCoating.Core.Entities; using PowderCoating.Infrastructure.Data; namespace PowderCoating.Infrastructure.Services; /// /// Database-backed key/value store for platform-wide configuration settings managed by /// SuperAdmins at /PlatformSettings. Settings are persisted in the PlatformSettings /// table as free-form strings; callers are responsible for parsing typed values (booleans, ints, /// etc.) from the returned strings. Rows are seeded at startup so that every expected key always /// has a row — the guard that inserts a missing row is a safety net for /// future migrations, not the normal path. /// public class PlatformSettingsService : IPlatformSettingsService { private readonly ApplicationDbContext _db; /// /// Constructs the service with a direct reference. /// Direct context access is used (rather than a repository) because /// PlatformSetting does not inherit BaseEntity and therefore is not managed /// by the generic Repository<T> or filtered by the global query filters. /// public PlatformSettingsService(ApplicationDbContext db) { _db = db; } /// /// Retrieves the value for the given , or null when the key /// does not exist. Uses AsNoTracking because reads are more frequent than writes and /// the caller never modifies the returned value directly. /// public async Task GetAsync(string key) { var setting = await _db.PlatformSettings .AsNoTracking() .FirstOrDefaultAsync(s => s.Key == key); return setting?.Value; } /// /// Creates or updates the platform setting identified by . /// Records (typically the SuperAdmin's username) and /// UpdatedAt (UTC) for audit purposes. Inserts a new row if the key is missing — /// this should only happen when a new setting key is introduced without a corresponding /// seed migration. Calls SaveChangesAsync directly rather than going through /// IUnitOfWork to avoid inadvertently flushing unrelated tracked changes from the /// caller's scope. /// public async Task SetAsync(string key, string? value, string? updatedBy = null) { var setting = await _db.PlatformSettings.FirstOrDefaultAsync(s => s.Key == key); if (setting == null) { // Shouldn't happen in normal use (rows are seeded), but handle gracefully setting = new PlatformSetting { Key = key }; _db.PlatformSettings.Add(setting); } setting.Value = value; setting.UpdatedAt = DateTime.UtcNow; setting.UpdatedBy = updatedBy; await _db.SaveChangesAsync(); } /// /// Returns all platform settings ordered by group then key, suitable for rendering the /// SuperAdmin settings management UI. Results are read with AsNoTracking for /// performance; the UI renders them read-only and individual edits go through /// . /// public async Task> GetAllAsync() { return await _db.PlatformSettings .AsNoTracking() .OrderBy(s => s.GroupName) .ThenBy(s => s.Key) .ToListAsync(); } }