Files
Dhananjaya99 bffc9b1686 first commit
2026-09-28 11:44:26 +05:30

328 lines
14 KiB
C#

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 System.Net.Sockets;
namespace Fitness_core_BE.Services.Ticket
{
public class TicketService : ITicketService
{
private readonly ITicketRepository _repository;
private readonly UserRoleHelper _userRoleHelper;
private readonly IUnitOfWork _uow;
private readonly IActivityLogService _activityLogService;
public TicketService(ITicketRepository repository, UserRoleHelper userRoleHelper, IUnitOfWork uow, IActivityLogService activityLogService)
{
_repository = repository;
_userRoleHelper = userRoleHelper;
_uow = uow;
_activityLogService = activityLogService;
}
public async Task<object> GetTicketList(object payload, HttpContext httpContext)
{
try
{
var tickets = await _repository.GetTicketListAsync();
return tickets;
}
catch
{
throw;
}
}
public async Task<object> GetTicketByUserId(object payload, HttpContext httpContext)
{
try
{
// Guid userId = Guid.TryParse(httpContext.Items["UserId"]?.ToString(), out var parsedUserId)
// ? parsedUserId
// : throw new UnauthorizedAccessException("User ID not found in context");
// Guid userId = Guid.Parse("a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d"); // Testing purposes
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
var tickets = await _repository.GetTicketByUserIdAsync(userId);
return tickets;
}
catch
{
throw;
}
}
public async Task<object> GetTicketById(object payload, HttpContext httpContext)
{
try
{
var data = DeserializePayload.Deserialize(payload);
Guid ticketId = Guid.Parse(data["ticketId"].GetString()!);
var ticket = await _repository.GetByTicketIdAsync(ticketId);
if (ticket == null)
throw new KeyNotFoundException($"Ticket with ID {ticketId} not found");
if (ticket.UserId != DataExtractor.GetUserIdFromContext(httpContext))
throw new UnauthorizedAccessException("You do not have permission to view this ticket.");
return ticket;
}
catch
{
throw;
}
}
public async Task<object> GetTicketCategoryList(object payload, HttpContext httpContext)
{
try
{
var categories = await _repository.GetTicketCategoryListAsync();
return categories;
}
catch
{
throw;
}
}
public async Task<object> CreateTicket(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
// Parse userId from context
// Guid userId = Guid.TryParse(httpContext.Items["UserId"]?.ToString(), out var parsedUserId)
// ? parsedUserId
// : throw new UnauthorizedAccessException("User ID not found in context");
// Guid userId = Guid.Parse("a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d"); // Testing purposes
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
var ticket = new Fitness_core_BE.Models.Ticket
{
MainReason = data["mainReason"].GetString()!,
FKTicketCategoryId = data.ContainsKey("ticketCategoryId") && !string.IsNullOrEmpty(data["ticketCategoryId"].GetString())
? Guid.Parse(data["ticketCategoryId"].GetString()!)
: (Guid?)null,
TicketStatus = data.ContainsKey("ticketStatus") && !string.IsNullOrEmpty(data["ticketStatus"].GetString())
? Enum.Parse<Fitness_core_BE.Models.Enums.TicketStatusEnum>(data["ticketStatus"].GetString()!)
: Fitness_core_BE.Models.Enums.TicketStatusEnum.Pending,
FKUserId = userId,
CreateDate = DateTime.UtcNow
};
await _repository.CreateTicketAsync(ticket);
await _uow.CommitAsync();
// Log activity - non-blocking, failures won't crash the operation
try
{
await _activityLogService.LogActivity(new { description = $"Ticket created with ID {ticket.TicketId}" }, httpContext);
}
catch (Exception logEx)
{
Console.WriteLine($"Activity log failed (non-critical): {logEx.Message}");
}
return ticket;
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
public async Task<object> UpdateTicket(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
Guid ticketId = Guid.Parse(data["ticketId"].GetString()!);
var ticket = await _repository.GetByTicketIdAsync(ticketId) ?? throw new KeyNotFoundException($"Ticket with ID {ticketId} not found.");
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
if (ticket.UserId != userId)
throw new UnauthorizedAccessException("You do not have permission to update this ticket.");
ticket.MainReason = data.ContainsKey("mainReason") && !string.IsNullOrEmpty(data["mainReason"].GetString())
? data["mainReason"].GetString()!
: ticket.MainReason;
ticket.TicketCategoryId = data.ContainsKey("ticketCategoryId") && !string.IsNullOrEmpty(data["ticketCategoryId"].GetString())
? Guid.Parse(data["ticketCategoryId"].GetString()!)
: ticket.TicketCategoryId;
await _repository.UpdateTicketAsync(ticket);
await _uow.CommitAsync();
return ticket;
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
public async Task<object> SendMessage(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
// Parse userId from context
// Guid userId = Guid.TryParse(httpContext.Items["UserId"]?.ToString(), out var parsedUserId)
// ? parsedUserId
// : throw new UnauthorizedAccessException("User ID not found in context");
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
Guid? adminId = await _userRoleHelper.GetAdminId(userId);
bool isAdmin = adminId.HasValue;
Guid ticketId = Guid.Parse(data["ticketId"].GetString()!);
var ticket = await _repository.GetByTicketIdAsync(ticketId)
?? throw new KeyNotFoundException($"Ticket with ID {ticketId} not found.");
if (!isAdmin && ticket.UserId != userId)
throw new UnauthorizedAccessException("You do not have permission to message this ticket.");
var ticketMessage = new TicketMessage
{
Message = data["message"].GetString()!,
FKTicketId = ticketId,
IsSentByAdmin = isAdmin,
AttachmentURL = data.ContainsKey("attachmentURL") ? data["attachmentURL"].GetString() : null,
FKDocumentId = DataExtractor.GetNullableInt(data, "documentId"),
CreateDate = DateTime.UtcNow
};
// First admin reply moves a ticket from Pending to Open — nothing previously
// set this transition, so tickets sat in Pending forever once created.
if (isAdmin)
{
if (ticket.TicketStatus == Models.Enums.TicketStatusEnum.Pending)
{
await _repository.UpdateTicketStatusAsync(ticketId, Models.Enums.TicketStatusEnum.Open);
}
}
//Guid ticCatId = DataExtractor.GetRequiredGuid(data, "ticketCategoryId");
//Guid? TcatId = await _repository.GetTicketCatId("Chat");
//if (ticCatId == TcatId)
//{
//}
await _repository.SendMessageAsync(ticketMessage);
await _uow.CommitAsync();
return ticketMessage;
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
public async Task<object> SubmitTicketFeedback(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
Guid ticketId = Guid.Parse(data["ticketId"].GetString()!);
int rating = DataExtractor.GetRequiredInt(data, "rating");
string? feedback = data.TryGetValue("feedback", out var feedbackContent) && !string.IsNullOrEmpty(feedbackContent.GetString())
? DataExtractor.GetOptionalString(data, "feedback")
: null;
if (rating < 1 || rating > 5)
throw new ArgumentException("Rating must be between 1 and 5.");
var ticket = await _repository.GetByTicketIdAsync(ticketId) ?? throw new KeyNotFoundException($"Ticket with ID {ticketId} not found.");
if (ticket.UserId != DataExtractor.GetUserIdFromContext(httpContext))
throw new UnauthorizedAccessException("You do not have permission to submit feedback for this ticket.");
if (ticket.TicketStatus != Models.Enums.TicketStatusEnum.Closed)
throw new InvalidOperationException("Feedback can only be submitted after the ticket is closed.");
await _repository.SubmitTicketFeedbackAsync(ticketId, rating, feedback);
await _uow.CommitAsync();
return new { message = $"The feedback for ticket with ID {ticketId} submitted successfully." };
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
public async Task<object> CloseTicket(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
Guid ticketId = Guid.Parse(data["ticketId"].GetString()!);
var ticket = await _repository.GetByTicketIdAsync(ticketId)
?? throw new KeyNotFoundException($"Ticket with ID {ticketId} not found.");
if (ticket.UserId != DataExtractor.GetUserIdFromContext(httpContext))
throw new UnauthorizedAccessException("You do not have permission to close this ticket.");
await _repository.UpdateTicketStatusAsync(ticketId, Fitness_core_BE.Models.Enums.TicketStatusEnum.Closed);
await _uow.CommitAsync();
var updatedTicket = await _repository.GetByTicketIdAsync(ticketId);
if (updatedTicket == null)
throw new KeyNotFoundException($"Ticket with ID {ticketId} not found after update");
return updatedTicket;
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
public async Task<object> DeleteTicket(object payload, HttpContext httpContext)
{
await _uow.BeginAsync();
try
{
var data = DeserializePayload.Deserialize(payload);
Guid ticketId = Guid.Parse(data["ticketId"].GetString()!);
var ticket = await _repository.GetByTicketIdAsync(ticketId) ?? throw new KeyNotFoundException($"Ticket with ID {ticketId} not found.");
Guid userId = DataExtractor.GetUserIdFromContext(httpContext);
if (ticket.UserId != userId)
throw new UnauthorizedAccessException("You do not have permission to delete this ticket.");
await _repository.DeleteAsync(ticketId);
await _uow.CommitAsync();
var deletedTicket = await _repository.GetByTicketIdAsync(ticketId);
if (deletedTicket == null)
return true;
throw new ArgumentException($"Ticket with ID {ticketId} has not been deleted");
}
catch
{
await _uow.RollbackAsync();
throw;
}
}
}
}