using PlotLine.Data; using PlotLine.Models; using PlotLine.ViewModels; namespace PlotLine.Services; public interface IFeatureRequestService { Task CreateAsync(int userId, FeatureRequestCreateViewModel model); Task GetForUserAsync(int featureRequestId, int userId); Task GetForAdminAsync(int featureRequestId); Task> ListForUserAsync(int userId); Task> ListForAdminAsync(string? status); Task UpdateAdminFieldsAsync(AdminFeatureRequestUpdateViewModel model); Task AddUserReplyAsync(int featureRequestId, int userId, string messageBody); Task AddAdminReplyAsync(int featureRequestId, int adminUserId, string messageBody); Task> ListMessagesAsync(int featureRequestId); } public sealed class FeatureRequestService(IFeatureRequestRepository featureRequests) : IFeatureRequestService { public Task CreateAsync(int userId, FeatureRequestCreateViewModel model) { return featureRequests.CreateAsync( userId, Clean(model.Title), Clean(model.Description), CleanNullable(model.AppArea), CleanNullable(model.Importance)); } public Task GetForUserAsync(int featureRequestId, int userId) => featureRequests.GetForUserAsync(featureRequestId, userId); public Task GetForAdminAsync(int featureRequestId) => featureRequests.GetForAdminAsync(featureRequestId); public Task> ListForUserAsync(int userId) => featureRequests.ListForUserAsync(userId); public Task> ListForAdminAsync(string? status) => featureRequests.ListForAdminAsync(FeatureRequestStatuses.IsValid(status) ? status : null); public async Task UpdateAdminFieldsAsync(AdminFeatureRequestUpdateViewModel model) { if (!FeatureRequestStatuses.IsValid(model.Status)) { return false; } var updated = await featureRequests.UpdateStatusAsync(model.FeatureRequestID, model.Status, model.IsPublicCandidate); if (updated is null) { return false; } await featureRequests.UpdateAdminNotesAsync(model.FeatureRequestID, CleanNullable(model.AdminNotes)); return true; } public async Task AddUserReplyAsync(int featureRequestId, int userId, string messageBody) { var message = await featureRequests.AddMessageAsync(featureRequestId, userId, isAdmin: false, Clean(messageBody)); return message is not null; } public async Task AddAdminReplyAsync(int featureRequestId, int adminUserId, string messageBody) { var message = await featureRequests.AddMessageAsync(featureRequestId, adminUserId, isAdmin: true, Clean(messageBody)); return message is not null; } public Task> ListMessagesAsync(int featureRequestId) => featureRequests.ListMessagesAsync(featureRequestId); private static string Clean(string value) => value.Trim(); private static string? CleanNullable(string? value) => string.IsNullOrWhiteSpace(value) ? null : value.Trim(); }