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();
}
}