Files
Core_Be/Services/FeedService.cs
Dhananjaya99 bffc9b1686 first commit
2026-09-28 11:44:26 +05:30

356 lines
13 KiB
C#

using Fitness_core_BE.Exceptions;
using Fitness_core_BE.Helpers;
using Fitness_core_BE.Infra.UoW;
using Fitness_core_BE.Interfaces;
using Fitness_core_BE.Interfaces.Services;
using Fitness_core_BE.Models;
using Fitness_core_BE.Models.IOs;
namespace Fitness_core_BE.Services.Feed
{
public class FeedService : IFeedService
{
// DocumentTypes.DocumentId for FEED_POST (seeded in CentralDbContext/AppDBContext).
private const int FeedPostDocumentTypeId = 1005;
private readonly IFeedRepository _repository;
private readonly UserRoleHelper _userRoleHelper;
private readonly IUnitOfWork _uow;
private readonly IActivityLogService _activityLogService;
private readonly IDocumentService _documentService;
private readonly IPushNotificationService _pushNotificationService;
public FeedService(IFeedRepository repository, UserRoleHelper userRoleHelper, IUnitOfWork uow, IActivityLogService activityLogService, IDocumentService documentService, IPushNotificationService pushNotificationService)
{
_repository = repository;
_userRoleHelper = userRoleHelper;
_uow = uow;
_activityLogService = activityLogService;
_documentService = documentService;
_pushNotificationService = pushNotificationService;
}
public async Task<object> GetFeedPostById(object payload, HttpContext httpContext)
{
var data = DeserializePayload.Deserialize(payload);
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
Guid postId = DataExtractor.GetRequiredGuid(data, "postId");
FeedPost post = await _repository.GetFeedPostByIdAsync(userId, postId);
return post;
}
public async Task<object> GetFeedForCustomer(object payload, HttpContext httpContext)
{
try
{
var data = DeserializePayload.Deserialize(payload);
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
int skip = data.ContainsKey("skip") && data["skip"].TryGetInt32(out var skipValue) ? skipValue : 0;
int take = data.ContainsKey("take") && data["take"].TryGetInt32(out var takeValue) ? takeValue : 10;
// A customer with no active gym has no single client feed to scope to — the
// repository already falls back to the platform-wide feed for them (clientId
// stays null), so this no longer short-circuits to an empty list.
var (clientId, feedList) =
await _repository.GetFeedForCustomerAsync(userId, skip, take);
var feedListWithLikeCount = new List<object>();
foreach (var feed in feedList)
{
var likeCount = await _repository.GetLikeCountAsync(feed.FeedPostId);
feedListWithLikeCount.Add(new
{
feedPostId = feed.FeedPostId,
caption = feed.Caption,
description = feed.Description,
userId = feed.FKUserId,
docId = feed.FkDocId,
isActive = feed.IsActive,
createdAt = feed.CreatedAt,
creator = feed.User.UserName,
likeCount,
clientId = clientId
});
}
return feedListWithLikeCount;
}
catch
{
throw;
}
}
//like
public async Task<object> LikeAsync(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
Guid postId = Guid.Parse(data["postId"].GetString()!);
if (!await _repository.IsLikedAsync(postId, userId))
{
await _repository.AddLikeAsync(postId, userId);
await _uow.CommitAsync();
return new { success = true, message = "Post liked successfully" };
}
return new { success = false, message = "Post already liked" };
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
//check like
public async Task<object> IsLikedAsync(object payload, HttpContext httpContext)
{
try
{
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
var data = DeserializePayload.Deserialize(payload);
Guid postId = Guid.Parse(data["postId"].GetString()!);
bool isLiked = await _repository.IsLikedAsync(postId, userId);
return new { isLiked };
}
catch
{
throw;
}
}
public async Task<object> UnlikeAsync(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
Guid postId = Guid.Parse(data["postId"].GetString()!);
Guid userId = Guid.Parse(data["userId"].GetString()!);
if (await _repository.IsLikedAsync(postId, userId))
{
await _repository.RemoveLikeAsync(postId, userId);
await _uow.CommitAsync();
return new { success = true, message = "Post unliked successfully" };
}
return new { success = false, message = "Post not liked yet" };
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
//create feed
public async Task<object> CreateFeed(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
// Tag every attachment with the FEED_POST document type unless the caller
// already chose one. Must match a DocumentTypes row (UserDocuments FKs to it).
object uploadPayload = payload;
if (data.TryGetValue("document", out var documentsElement) &&
documentsElement.ValueKind == System.Text.Json.JsonValueKind.Array)
{
var payloadJson = System.Text.Json.JsonSerializer.Serialize(data);
var payloadDict = System.Text.Json.JsonSerializer.Deserialize<Dictionary<string, object>>(
payloadJson) ?? new Dictionary<string, object>();
var documentsArray = System.Text.Json.JsonSerializer.Deserialize<List<Dictionary<string, object>>>(
documentsElement.GetRawText()) ?? new List<Dictionary<string, object>>();
foreach (var document in documentsArray)
{
if (!document.ContainsKey("FileType"))
{
document["FileType"] = FeedPostDocumentTypeId;
}
}
payloadDict["document"] = documentsArray;
uploadPayload = payloadDict;
}
var docResponseObj = await _documentService.UploadDocument(uploadPayload, httpContext);
dynamic docResponse = docResponseObj;
if (docResponse == null || docResponse?.uploadResults == null || docResponse?.uploadResults.Count == 0)
{
await _uow.RollbackAsync();
return new { success = false, message = "Document upload failed" };
}
var firstDoc = docResponse?.uploadResults[0];
int docId = firstDoc?.DocumentId ?? 0;
var feedPost = new FeedPost
{
Caption = data.ContainsKey("caption") ? data["caption"].GetString() : null,
Description = data.ContainsKey("description") ? data["description"].GetString() : null,
FkDocId = docId,
FKUserId = userId
};
await _repository.CreateFeedAsync(feedPost);
await _uow.CommitAsync();
try
{
var customerIds = await _repository.GetActiveCustomerIdsByPosterUserIdAsync(userId);
if (customerIds.Count > 0)
{
var caption = feedPost.Caption;
var body = string.IsNullOrWhiteSpace(caption)
? "Your gym shared a new post. Tap to view."
: caption!.Length > 120 ? caption[..120] + "…" : caption;
await _pushNotificationService.NotifyCustomersAsync(
customerIds,
"New post from your gym",
body,
"FeedPostCreated",
"MainTabs",
new { screen = "Connect" }
);
}
}
catch (Exception notifyEx)
{
Console.WriteLine($"Push notification failed (non-critical): {notifyEx.Message}");
}
return new { success = true, message = "Feed created successfully" };
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
public async Task<object> ShowFeedByClient(object payload, HttpContext httpContext)
{
try
{
var data = DeserializePayload.Deserialize(payload);
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
Guid clientId = await _userRoleHelper.GetClientId(userId);
var feedList = await _repository.GetFeedByClientAsync(clientId);
if (feedList == null || !feedList.Any())
{
return new { success = false, message = "No feeds found", data = new List<object>() };
}
var FeedListWithDoc = new List<object>();
foreach (var feed in feedList)
{
object? documentData = null;
if (feed.FkDocId.HasValue)
{
try
{
var docPayload = new { documentId = feed.FkDocId.Value };
documentData = await _documentService.GetDocumentById(docPayload, httpContext);
}
catch
{
documentData = null;
}
}
var likeCount = await _repository.GetLikeCountAsync(feed.FeedPostId);
FeedListWithDoc.Add(new
{
feedPostId = feed.FeedPostId,
caption = feed.Caption,
description = feed.Description,
userId = feed.FKUserId,
docId = feed.FkDocId,
isActive = feed.IsActive,
createdAt = feed.CreatedAt,
likeCount = likeCount,
document = documentData
});
}
return new { success = true, message = "Feeds retrieved successfully", data = FeedListWithDoc };
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
public async Task<object> DeleteFeedByPostId(object payload, HttpContext httpContext)
{
var data = DeserializePayload.Deserialize(payload);
Guid createUserId = DataExtractor.GetUserIdFromContext(httpContext);
Guid postId = DataExtractor.GetRequiredGuid(data, "postId");
await _uow.BeginAsync();
try
{
var result =await _repository.DeletePostPostIdAsync(createUserId, postId);
await _uow.CommitAsync();
return result;
}
catch
{
await _uow.RollbackAsync();
throw new BadRequestException ("delete post failed") ;
}
}
}
}