using Fitness_core_BE.Models; using Fitness_core_BE.Interfaces; using Fitness_core_BE.DTOs.Ticket; using Microsoft.EntityFrameworkCore; using Fitness_core_BE.Exceptions; namespace Fitness_core_BE.Repos { public class TicketRepository : ITicketRepository { private readonly CentralDbContext _dbContext; public TicketRepository(CentralDbContext dbContext) { _dbContext = dbContext; } public async Task GetTicketCatId (string type) { Guid TicketCatId = await _dbContext.TicketCategories .Where(tc => tc.TicketCategoryName == type && tc.IsActive) .Select(tc => tc.TicketCategoryId) .FirstOrDefaultAsync(); return TicketCatId; } public async Task> GetTicketListAsync(CancellationToken ct = default) { return await _dbContext.Tickets .AsNoTracking() .Include(t => t.User) .Include(t => t.Admin) .Include(t => t.TicketCategory) .Where(t => t.IsActive) .OrderByDescending(t => t.CreateDate) .Select(t => new TicketDto { TicketId = t.TicketId, MainReason = t.MainReason, CreateDate = t.CreateDate, UserId = t.FKUserId, UserName = t.User != null ? t.User.UserName : "", UserEmail = t.User != null ? t.User.Email : "", AdminId = t.FKAssignerId, AdminName = t.Admin != null ? t.Admin.AdminName : null, TicketCategoryId = t.FKTicketCategoryId, TicketCategoryName = t.TicketCategory != null ? t.TicketCategory.TicketCategoryName : null, PriorityLevel = t.TicketCategory != null ? t.TicketCategory.PriorityLevel : (Fitness_core_BE.Models.Enums.PriorityLevel?)null, UserRating = t.UserRating, TicketStatus = t.TicketStatus }) .ToListAsync(ct); } public async Task> GetTicketByUserIdAsync(Guid userId, CancellationToken ct = default) { return await _dbContext.Tickets .AsNoTracking() .Include(t => t.User) .Include(t => t.Admin) .Include(t => t.TicketCategory) .Where(t => t.FKUserId == userId && t.IsActive) .OrderByDescending(t => t.CreateDate) .Select(t => new TicketDto { TicketId = t.TicketId, MainReason = t.MainReason, CreateDate = t.CreateDate, UserId = t.FKUserId, UserName = t.User != null ? t.User.UserName : "", UserEmail = t.User != null ? t.User.Email : "", AdminId = t.FKAssignerId, AdminName = t.Admin != null ? t.Admin.AdminName : null, TicketCategoryId = t.FKTicketCategoryId, TicketCategoryName = t.TicketCategory != null ? t.TicketCategory.TicketCategoryName : null, PriorityLevel = t.TicketCategory != null ? t.TicketCategory.PriorityLevel : (Fitness_core_BE.Models.Enums.PriorityLevel?)null, UserRating = t.UserRating, TicketStatus = t.TicketStatus }) .ToListAsync(ct); } public async Task GetByTicketIdAsync(Guid id, CancellationToken ct = default) { var ticket = await _dbContext.Tickets .AsNoTracking() .Include(t => t.User) .Include(t => t.Admin) .Include(t => t.TicketCategory) .Include(t => t.Messages) .FirstOrDefaultAsync(t => t.TicketId == id && t.IsActive, ct); if (ticket == null) return null; return new TicketDetailDto { TicketId = ticket.TicketId, MainReason = ticket.MainReason, CreateDate = ticket.CreateDate, UserId = ticket.FKUserId, UserName = ticket.User?.UserName ?? "", UserEmail = ticket.User?.Email ?? "", UserPhoneNumber = ticket.User?.PhoneNumber ?? "", AdminId = ticket.FKAssignerId, AdminName = ticket.Admin?.AdminName, AdminPhoneNumber = ticket.Admin?.PhoneNumber, TicketCategoryId = ticket.FKTicketCategoryId, TicketCategoryName = ticket.TicketCategory?.TicketCategoryName, PriorityLevel = ticket.TicketCategory?.PriorityLevel, TicketStatus = ticket.TicketStatus, UserRating = ticket.UserRating, UserFeedback = ticket.UserFeedback, FeedbackAt = ticket.FeedbackAt, Messages = ticket.Messages?.Select(m => new TicketMessageDto { MessageId = m.MessageId, IsSentByAdmin = m.IsSentByAdmin, Message = m.Message, FKDocumentId = m.FKDocumentId, AttachmentURL = m.AttachmentURL, CreateDate = m.CreateDate }).OrderBy(m => m.CreateDate).ToList() ?? new List() }; } public Task CreateTicketAsync(Ticket ticket, CancellationToken ct = default) { _dbContext.Tickets.Add(ticket); return Task.FromResult(ticket); } public async Task UpdateTicketAsync(TicketDetailDto ticketDto, CancellationToken ct = default) { Ticket ticket = await _dbContext.Tickets.FirstOrDefaultAsync(t => t.TicketId == ticketDto.TicketId, ct) ?? throw new NotFoundException($"Ticket with ID {ticketDto.TicketId} not found"); ticket.MainReason = ticketDto.MainReason; ticket.FKTicketCategoryId = ticketDto.TicketCategoryId; _dbContext.Tickets.Update(ticket); return ticket; } public async Task DeleteAsync(Guid id, CancellationToken ct = default) { var entity = await _dbContext.Tickets.FirstOrDefaultAsync(t => t.TicketId == id, ct); if (entity == null) return false; entity.IsActive = false; return true; } // Ticket category operations public async Task> GetTicketCategoryListAsync(CancellationToken ct = default) { return await _dbContext.TicketCategories .AsNoTracking() .Where(tc => tc.IsActive) .OrderBy(tc => tc.TicketCategoryName) .ToListAsync(ct); } public async Task GetTicketCategoryByIdAsync(Guid id, CancellationToken ct = default) { return await _dbContext.TicketCategories .AsNoTracking() .FirstOrDefaultAsync(tc => tc.TicketCategoryId == id && tc.IsActive, ct); } // Ticket message operations public async Task SendMessageAsync(TicketMessage ticketMessage, CancellationToken ct = default) { _dbContext.TicketMessages.Add(ticketMessage); return ticketMessage; } public async Task SubmitTicketFeedbackAsync(Guid ticketId, int rating, string? feedback, CancellationToken ct = default) { var entity = await _dbContext.Tickets.FirstOrDefaultAsync(t => t.TicketId == ticketId, ct) ?? throw new NotFoundException($"Ticket with ID {ticketId} not found"); entity.UserRating = rating; if (feedback != null) entity.UserFeedback = feedback; entity.FeedbackAt = DateTime.Now; _dbContext.Tickets.Update(entity); return entity; } public async Task UpdateTicketStatusAsync(Guid ticketId, Fitness_core_BE.Models.Enums.TicketStatusEnum statusCode) { var ticket = await _dbContext.Tickets.FirstOrDefaultAsync(t => t.TicketId == ticketId); if (ticket == null) throw new NotFoundException($"Ticket with ID {ticketId} not found"); ticket.TicketStatus = statusCode; } } }