using System.Text.Json; using FBCKBLL.Interfaces; using FBCKDAL.DTOs; using FBCKDAL.Interfaces; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.Login; using GB5Shared.EventLogPublish; using static GB5Shared.GB5Constant.Constant; using GB5Shared.Resource.Response; using GB5Shared.Telemetry; using GB5Shared.Validation; using Microsoft.Extensions.Logging; namespace FBCKBLL.Implementations; public class FeedbackBLL : IFeedbackBLL { private readonly IFeedbackDAL _dal; private readonly IValidation _validation; private readonly KeyInvalidate _keyInvalidate; private readonly EventLogPublish _eventLog; private readonly ILogger _logger; public FeedbackBLL(IFeedbackDAL dal, IValidation validation, KeyInvalidate keyInvalidate, EventLogPublish eventLog, ILogger logger) { _dal = dal; _validation = validation; _keyInvalidate = keyInvalidate; _eventLog = eventLog; _logger = logger; } public async Task GetFeedbackAsync(int feedbackId, LoginDTO login, CancellationToken ct) { var dto = await _dal.GetFeedbackAsync(feedbackId, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(dto); } public async Task GetFeedbackListAsync(int targetEmployeeId, int responderId, short status, int page, int pageSize, LoginDTO login, CancellationToken ct) { var list = await _dal.GetFeedbackListAsync(targetEmployeeId, responderId, status, page, pageSize, login, ct).ConfigureAwait(false); return JsonSerializer.Serialize(list); } public async Task RequestFeedbackAsync(FeedbackDTO dto, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-feedback-request", new { dto.TargetEmployeeId, dto.ResponderId }); await _validation.NotEmpty(dto.QuestionsJson, nameof(dto.QuestionsJson)).ConfigureAwait(false); dto.Status = 0; // Requested GB5Trace.Step("save-feedback-request", new { dto.TargetEmployeeId }); var savedId = await _dal.InsertFeedbackAsync(dto, login, ct).ConfigureAwait(false); GB5Trace.Step("event-publish", new { EventTypeId = EventTypeConstant.SAVEFBCKREQUESTEVENTTYPEID }); await _eventLog.PublishEventLogAsync("Feedback Requested", nameof(FeedbackDTO), EventTypeConstant.SAVEFBCKREQUESTEVENTTYPEID, savedId, login, ct: ct).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration(0, EntityConstant.OBJECTFEEDBACK, CacheKeyLevel.USER_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return $"{SuccessResponse.SaveSuccessMessage} {savedId}"; } catch (Exception ex) { GB5Trace.MarkFailed("feedback-request-failed", ex); _logger.LogError(ex, "RequestFeedback failed for TargetEmployee {TargetEmployeeId}", dto.TargetEmployeeId); throw; } } public async Task SubmitFeedbackAsync(int feedbackId, string responsesJson, decimal overallRating, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-feedback-submit", new { feedbackId }); var feedback = await _dal.GetFeedbackAsync(feedbackId, login, ct).ConfigureAwait(false); if (feedback is null) return "Feedback not found."; if (feedback.Status is 2 or 3) return "Cannot submit feedback that is already submitted or declined."; GB5Trace.Step("save-feedback-submit", new { feedbackId }); await _dal.UpdateFeedbackResponseAsync(feedbackId, responsesJson, overallRating, 2, login, ct).ConfigureAwait(false); GB5Trace.Step("event-publish", new { EventTypeId = EventTypeConstant.SUBMITFBCKRESPONSEEVENTTYPEID }); await _eventLog.PublishEventLogAsync("Feedback Submitted", nameof(FeedbackDTO), EventTypeConstant.SUBMITFBCKRESPONSEEVENTTYPEID, feedbackId, login, ct: ct).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration(0, EntityConstant.OBJECTFEEDBACK, CacheKeyLevel.USER_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("feedback-submit-failed", ex); _logger.LogError(ex, "SubmitFeedback failed for FeedbackId {FeedbackId}", feedbackId); throw; } } public async Task DeclineFeedbackAsync(int feedbackId, LoginDTO login, CancellationToken ct) { try { GB5Trace.Step("validate-feedback-decline", new { feedbackId }); var feedback = await _dal.GetFeedbackAsync(feedbackId, login, ct).ConfigureAwait(false); if (feedback is null) return "Feedback not found."; if (feedback.Status is 2 or 3) return "Cannot decline feedback that is already submitted or declined."; GB5Trace.Step("save-feedback-decline", new { feedbackId }); await _dal.UpdateFeedbackStatusAsync(feedbackId, 3, login, ct).ConfigureAwait(false); GB5Trace.Step("event-publish", new { EventTypeId = EventTypeConstant.DECLINEFBCKFEEDBACKEVENTTYPEID }); await _eventLog.PublishEventLogAsync("Feedback Declined", nameof(FeedbackDTO), EventTypeConstant.DECLINEFBCKFEEDBACKEVENTTYPEID, feedbackId, login, ct: ct).ConfigureAwait(false); var cacheKey = new CacheKeyGeneration().KeyGeneration(0, EntityConstant.OBJECTFEEDBACK, CacheKeyLevel.USER_LEVEL, login); await _keyInvalidate.AllInvalidateCache(cacheKey).ConfigureAwait(false); return SuccessResponse.UpdateSuccess; } catch (Exception ex) { GB5Trace.MarkFailed("feedback-decline-failed", ex); _logger.LogError(ex, "DeclineFeedback failed for FeedbackId {FeedbackId}", feedbackId); throw; } } public async Task GetFeedbackSummaryForESSAsync(int employeeId, LoginDTO login, CancellationToken ct) => await _dal.GetFeedbackSummaryAsync(employeeId, login, ct).ConfigureAwait(false); }