139 lines
4.8 KiB
C#
139 lines
4.8 KiB
C#
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.Helpers;
|
|
|
|
namespace Fitness_core_BE.Services.Chat
|
|
{
|
|
public class ChatService : IChatService
|
|
{
|
|
private const int MAX_MESSAGE_LENGTH = 100000;
|
|
|
|
private readonly IChatRepo _repository;
|
|
private readonly IUnitOfWork _uow;
|
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
|
|
public ChatService(IChatRepo repository, IUnitOfWork uow, IHttpContextAccessor httpContextAccessor)
|
|
{
|
|
_repository = repository;
|
|
_uow = uow;
|
|
_httpContextAccessor = httpContextAccessor;
|
|
}
|
|
|
|
public async Task<object> GetOrCreateChatAsync(object payload)
|
|
{
|
|
var httpContext = _httpContextAccessor.HttpContext;
|
|
var data = DeserializePayload.Deserialize(payload);
|
|
Guid currentUserId= DataExtractor.GetUserIdFromContext(httpContext);
|
|
Guid otherUserId = DataExtractor.GetRequiredGuid(data, "otherUserId");
|
|
|
|
if (currentUserId == otherUserId)
|
|
throw new InvalidOperationException("Cannot create chat with yourself.");
|
|
|
|
await _uow.BeginAsync();
|
|
|
|
try
|
|
{
|
|
var existingChat =
|
|
await _repository.GetChatBetweenUsersAsync(currentUserId, otherUserId);
|
|
|
|
if (existingChat != null && existingChat.IsAcitve)
|
|
{
|
|
await _uow.CommitAsync();
|
|
return existingChat;
|
|
}
|
|
|
|
var chat = new Models.Chat
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
FKSenderId = currentUserId,
|
|
FKReceiverId = otherUserId
|
|
};
|
|
|
|
await _repository.CreateChatAsync(chat);
|
|
await _uow.CommitAsync();
|
|
|
|
return chat;
|
|
}
|
|
catch
|
|
{
|
|
await _uow.RollbackAsync();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<object> SendMessageAsync(object payload)
|
|
{
|
|
var data = DeserializePayload.Deserialize(payload);
|
|
Guid chatId = DataExtractor.GetRequiredGuid(data, "chatId");
|
|
Guid senderId = DataExtractor.GetRequiredGuid(data, "senderId");
|
|
string message = DataExtractor.GetRequiredString(data, "message");
|
|
string type = DataExtractor.GetRequiredString(data, "type");
|
|
|
|
if (string.IsNullOrWhiteSpace(message))
|
|
throw new ArgumentException("Message cannot be empty.");
|
|
|
|
message = message.Trim();
|
|
|
|
if (message.Length > MAX_MESSAGE_LENGTH)
|
|
throw new ArgumentException($"Message exceeds {MAX_MESSAGE_LENGTH} characters.");
|
|
|
|
await _uow.BeginAsync();
|
|
|
|
try
|
|
{
|
|
var chat = await _repository.GetChatByIdAsync(chatId);
|
|
|
|
if (chat == null || !chat.IsAcitve)
|
|
throw new KeyNotFoundException("Chat not found or inactive.");
|
|
|
|
if (senderId != chat.FKSenderId && senderId != chat.FKReceiverId)
|
|
throw new UnauthorizedAccessException("User not part of this chat.");
|
|
|
|
var chatMessage = new ChatMessages
|
|
{
|
|
Id = Guid.NewGuid(),
|
|
FKChatId = chatId,
|
|
FKSenderId = senderId,
|
|
Message = message,
|
|
Type = type,
|
|
CreatedAt = DateTime.UtcNow,
|
|
IsAcitve = true
|
|
};
|
|
|
|
await _repository.AddMessageAsync(chatMessage);
|
|
await _uow.CommitAsync();
|
|
|
|
return chatMessage;
|
|
}
|
|
catch
|
|
{
|
|
await _uow.RollbackAsync();
|
|
throw;
|
|
}
|
|
}
|
|
|
|
public async Task<object> GetMessagesAsync(object payload)
|
|
{
|
|
var data = DeserializePayload.Deserialize(payload);
|
|
Guid chatId = DataExtractor.GetRequiredGuid(data, "chatId");
|
|
Guid userId = DataExtractor.GetRequiredGuid(data, "userId");
|
|
int skip = DataExtractor.GetRequiredInt(data, "skip");
|
|
int take = DataExtractor.GetRequiredInt(data, "take");
|
|
if (take <= 0 || take > 100)
|
|
take = 30;
|
|
|
|
if (!await CanUserAccessChatAsync(chatId, userId))
|
|
throw new UnauthorizedAccessException("User not allowed to view this chat.");
|
|
|
|
return await _repository.GetMessagesAsync(chatId, skip, take);
|
|
}
|
|
|
|
public async Task<bool> CanUserAccessChatAsync(Guid chatId, Guid userId)
|
|
{
|
|
return await _repository.IsUserInChatAsync(chatId, userId);
|
|
}
|
|
}
|
|
}
|