using Microsoft.EntityFrameworkCore; using vendorApproverBackend.Data; using vendorApproverBackend.Entities; using vendorApproverBackend.Enums; using vendorApproverBackend.Requests; using vendorApproverBackend.Responses; using vendorApproverBackend.Interfaces; namespace vendorApproverBackend.Services { public class EmployeeApplicationService { private readonly DataContext _context; private readonly UserService _userService; private readonly INotificationService _notificationService; public EmployeeApplicationService(DataContext context, UserService userService, INotificationService notificationService) { _context = context; _userService = userService; _notificationService = notificationService; } public async Task CreateApplicationAsync(long userId, CreateEmployeeApplicationRequest dto) { var user = await _userService.FindByIdAsync(userId); if (user == null) { throw new KeyNotFoundException($"User with ID {userId} not found."); } var newApplication = new EmployeeApplication { UserId = userId, Type = dto.Type, Experience = dto.Experience, Qualifications = dto.Qualifications, Category = dto.Category, CertificationIds = dto.CertificationIds, Status = ApplicationStatus.SUBMITTED, SubmissionDate = DateTime.UtcNow }; if (dto.ApplicationCategoriesId != null && dto.ApplicationCategoriesId.Count > 0) { foreach (var categoryId in dto.ApplicationCategoriesId) { var category = await _context.ApplicationCategories.FindAsync(categoryId); if (category != null) { newApplication.ApplicationCategories.Add(category); } } } _context.EmployeeApplications.Add(newApplication); await _context.SaveChangesAsync(); await SendNewApplicationNotificationToAdmins(newApplication, user); return newApplication; } private async Task SendNewApplicationNotificationToAdmins(EmployeeApplication newApplication, User user) { try { var adminUserIds = await _userService.GetAdminUserIdsAsync(); if (adminUserIds.Any()) { var notification = new NotificationModel { SenderId = user.Id, Subject = "New Application Created", Content = $"New Application added by {user.Name}", Action = Action.NEW_APPLICATION, ActionId = newApplication.Id, LogUrl = "", Status = states.WAITING }; await _notificationService.SendNotificationToListOfUsers(adminUserIds, notification); } else { //_logger.LogWarning("No admin users found to send notification to"); } } catch (Exception ex) { // _logger.LogError(ex, "Failed to send notification for new PQ request {RequestId}", newRequest.Id); } } public async Task UpdateApplicationAsync(long applicationId, CreateEmployeeApplicationRequest dto) { var existingApplication = await _context.EmployeeApplications.FindAsync(applicationId); if (existingApplication == null || existingApplication.Status == ApplicationStatus.APPROVED) { return null; } if (dto.Type != null) { existingApplication.Type = dto.Type.Value; } if (dto.Experience != null) { existingApplication.Experience = dto.Experience; } if (dto.Qualifications != null) { existingApplication.Qualifications = dto.Qualifications; } if (dto.Qualifications != null) { existingApplication.CertificationIds = dto.CertificationIds; } existingApplication.Status = ApplicationStatus.SUBMITTED; if (dto.ApplicationCategoriesId != null && dto.ApplicationCategoriesId.Count > 0) { existingApplication.ApplicationCategories.Clear(); foreach (var categoryId in dto.ApplicationCategoriesId) { var category = await _context.ApplicationCategories.FindAsync(categoryId); if (category != null) { existingApplication.ApplicationCategories.Add(category); } } } _context.EmployeeApplications.Update(existingApplication); await _context.SaveChangesAsync(); return existingApplication; } public async Task UpdateApplicationStatusAsync(long applicationId, UpdateApplicationStatusRequest dto) { var existingApplication = await _context.EmployeeApplications .Include(a => a.User) .FirstOrDefaultAsync(a => a.Id == applicationId); if (existingApplication == null) { return null; } existingApplication.Status = dto.Status; if (dto.Status == ApplicationStatus.APPROVED) { var user = existingApplication.User; var applicationType = existingApplication.Type; user.Type = dto.Type; await _userService.UpdateUserAsync(user); } else if (dto.Status == ApplicationStatus.REJECTED) { existingApplication.Reason = dto.Reason; } _context.EmployeeApplications.Update(existingApplication); await _context.SaveChangesAsync(); return existingApplication; } public async Task FindByIdAsync(long applicationId) { return await _context.EmployeeApplications .Include(a => a.User) .FirstOrDefaultAsync(a => a.Id == applicationId); } public async Task DeleteApplicationAsync(long applicationId) { var application = await _context.EmployeeApplications.FindAsync(applicationId); if (application == null) { return false; } _context.EmployeeApplications.Remove(application); await _context.SaveChangesAsync(); return true; } public async Task> GetApplicationsByCriteriaAsync( int page, int size, long? userId = null, ApplicationStatus? status = null, EmployeeTypeEnum? type = null, DateTime? submissionDate = null, string? userName = null) { var query = _context.EmployeeApplications .Include(a => a.User) .Include(a => a.ApplicationCategories) .AsQueryable(); if (userId.HasValue) { query = query.Where(a => a.UserId == userId.Value); } if (status.HasValue) { query = query.Where(a => a.Status == status.Value); } if (type.HasValue) { query = query.Where(a => a.Type == type.Value); } if (submissionDate.HasValue) { var dateOnly = submissionDate.Value.Date; query = query.Where(a => a.SubmissionDate.HasValue && a.SubmissionDate.Value.Date == dateOnly); } if (!string.IsNullOrWhiteSpace(userName)) { var searchName = userName.ToLower(); query = query.Where(a => a.User.Name.ToLower().Contains(searchName)); } var totalCount = await query.CountAsync(); var items = await query .OrderByDescending(a => a.SubmissionDate) .Skip(page * size) .Take(size) .ToListAsync(); return new PagedResult(items, totalCount, page, size); } } }