using HelpDesk.Models.Entities; using HelpDesk.Models.Enums; using Microsoft.EntityFrameworkCore; namespace HelpDesk.Data.Repositories; public class TicketRepository : ITicketRepository { private readonly HelpDeskDbContext _context; public TicketRepository(HelpDeskDbContext context) { _context = context; } private IQueryable GetQueryable() => _context.Tickets .Include(t => t.Requester) .Include(t => t.Assignee) .Include(t => t.Group) .Include(t => t.SlaPolicy) .Include(t => t.Comments); public async Task GetByIdAsync(Guid id) => await GetQueryable().FirstOrDefaultAsync(t => t.Id == id); public async Task> GetAllAsync(TicketStatus? status, TicketPriority? priority, Guid? assigneeId, Guid? requesterId, int page = 1, int pageSize = 20) { var query = GetQueryable().AsQueryable(); if (status.HasValue) query = query.Where(t => t.Status == status.Value); if (priority.HasValue) query = query.Where(t => t.Priority == priority.Value); if (assigneeId.HasValue) query = query.Where(t => t.AssigneeId == assigneeId.Value); if (requesterId.HasValue) query = query.Where(t => t.RequesterId == requesterId.Value); return await query.OrderByDescending(t => t.CreatedAt) .Skip((page - 1) * pageSize) .Take(pageSize) .ToListAsync(); } public async Task GetCountAsync(TicketStatus? status, TicketPriority? priority, Guid? assigneeId, Guid? requesterId) { var query = _context.Tickets.AsQueryable(); if (status.HasValue) query = query.Where(t => t.Status == status.Value); if (priority.HasValue) query = query.Where(t => t.Priority == priority.Value); if (assigneeId.HasValue) query = query.Where(t => t.AssigneeId == assigneeId.Value); if (requesterId.HasValue) query = query.Where(t => t.RequesterId == requesterId.Value); return await query.CountAsync(); } public async Task CreateAsync(Ticket ticket) { _context.Tickets.Add(ticket); await _context.SaveChangesAsync(); return ticket; } public async Task UpdateAsync(Ticket ticket) { var existing = await _context.Tickets.FindAsync(ticket.Id); if (existing == null) return null; existing.Title = ticket.Title; existing.Description = ticket.Description; existing.Priority = ticket.Priority; existing.Status = ticket.Status; existing.AssigneeId = ticket.AssigneeId; existing.GroupId = ticket.GroupId; existing.SlaPolicyId = ticket.SlaPolicyId; existing.UpdatedAt = DateTime.UtcNow; if (ticket.Status == TicketStatus.Resolved && existing.ResolvedAt == null) existing.ResolvedAt = DateTime.UtcNow; if (ticket.Status == TicketStatus.Closed && existing.ClosedAt == null) existing.ClosedAt = DateTime.UtcNow; await _context.SaveChangesAsync(); return existing; } public async Task DeleteAsync(Guid id) { var ticket = await _context.Tickets.FindAsync(id); if (ticket == null) return false; _context.Tickets.Remove(ticket); await _context.SaveChangesAsync(); return true; } public async Task GetTotalCountAsync() => await _context.Tickets.CountAsync(); public async Task GetCountByStatusAsync(TicketStatus status) => await _context.Tickets.CountAsync(t => t.Status == status); public async Task GetCountByPriorityAsync(TicketPriority priority) => await _context.Tickets.CountAsync(t => t.Priority == priority); public async Task GetAverageResponseTimeAsync() { var tickets = await _context.Tickets .Where(t => t.Comments.Any()) .Select(t => new { t.CreatedAt, FirstCommentAt = t.Comments.OrderBy(c => c.CreatedAt).Select(c => c.CreatedAt).FirstOrDefault() }) .Where(t => t.FirstCommentAt != default(DateTime)) .ToListAsync(); if (!tickets.Any()) return 0; return tickets.Average(t => (t.FirstCommentAt - t.CreatedAt).TotalMinutes); } public async Task GetAverageResolutionTimeAsync() { var tickets = await _context.Tickets .Where(t => t.ResolvedAt.HasValue) .Select(t => new { t.CreatedAt, t.ResolvedAt }) .ToListAsync(); if (!tickets.Any()) return 0; return tickets.Average(t => (t.ResolvedAt!.Value - t.CreatedAt).TotalMinutes); } }