using Data.SeaHavenIndustries; using FluentValidation; using SeaHaven.DataServices.Interfaces; using SeaHaven.Services.DTOs; using SeaHaven.Services.Interfaces; using SeaHaven.Services.Validation; namespace SeaHaven.Services.Implementation { /// /// Follow-Up service implementation /// Contains business logic, validation, and orchestration for Follow-Up operations /// public class FollowUpService : IFollowUpService { private readonly IFollowUpDataService _followUpDataService; private readonly ICreateFollowUpValidation _createValidator; private readonly IUpdateFollowUpValidation _updateValidator; public FollowUpService( IFollowUpDataService followUpDataService, ICreateFollowUpValidation createValidator, IUpdateFollowUpValidation updateValidator) { _followUpDataService = followUpDataService; _createValidator = createValidator; _updateValidator = updateValidator; } public async Task GetFollowUpByIdAsync(int id) { var followUp = await _followUpDataService.GetByIdAsync(id); return followUp == null ? null : MapToDTO(followUp); } public async Task GetFollowUpByIdWithDetailsAsync(int id) { var followUp = await _followUpDataService.GetByIdWithDetailsAsync(id); return followUp == null ? null : MapToDTO(followUp); } public async Task> GetAllFollowUpsAsync() { var followUps = await _followUpDataService.GetAllAsync(); return followUps.Select(MapToDTO); } public async Task> GetFollowUpsByWorkOrderIdAsync(int workOrderId) { var followUps = await _followUpDataService.GetByWorkOrderIdAsync(workOrderId); return followUps.Select(MapToDTO); } public async Task> GetFollowUpsPagedAsync(int page, int pageSize, string? search = null, string? status = null) { var (items, totalCount) = await _followUpDataService.GetPagedAsync(page, pageSize, search); var filteredItems = items.AsEnumerable(); if (!string.IsNullOrWhiteSpace(status)) { filteredItems = filteredItems.Where(f => f.Status == status); } return new PagedResult { Items = filteredItems.Select(MapToDTO).ToList(), TotalCount = totalCount, Page = page, PageSize = pageSize }; } public async Task CreateFollowUpAsync(CreateFollowUpDTO dto, string userId) { var validationResult = await _createValidator.ValidateAsync(dto); if (!validationResult.IsValid) { throw new ValidationException(validationResult.Errors); } var followUp = new FollowUps { Reason = dto.Reason, ScheduleDate = dto.ScheduleDate, ScheduleStartTime = dto.ScheduleStartTime, Status = dto.Status, EmployeeId = dto.EmployeeId, WorkOrderId = dto.WorkOrderId, AccountId = dto.AccountId, LocationId = dto.LocationId, CreatedDate = DateTime.UtcNow, createdby = userId }; var created = await _followUpDataService.AddAsync(followUp); return MapToDTO(created); } public async Task UpdateFollowUpAsync(int id, UpdateFollowUpDTO dto, string userId) { var validationResult = await _updateValidator.ValidateAsync(dto); if (!validationResult.IsValid) { throw new ValidationException(validationResult.Errors); } var followUp = await _followUpDataService.GetByIdAsync(id); if (followUp == null) throw new InvalidOperationException($"Follow-Up with ID {id} not found"); if (dto.Reason != null) followUp.Reason = dto.Reason; if (dto.ScheduleDate.HasValue) followUp.ScheduleDate = dto.ScheduleDate.Value; if (dto.ScheduleStartTime.HasValue) followUp.ScheduleStartTime = dto.ScheduleStartTime.Value; if (dto.Status != null) followUp.Status = dto.Status; if (dto.EmployeeId.HasValue) followUp.EmployeeId = dto.EmployeeId; if (dto.WorkOrderId.HasValue) followUp.WorkOrderId = dto.WorkOrderId; if (dto.AccountId.HasValue) followUp.AccountId = dto.AccountId; if (dto.LocationId.HasValue) followUp.LocationId = dto.LocationId; followUp.LastModificationTime = DateTime.UtcNow; if (int.TryParse(userId, out int userIdInt)) followUp.LastModifierUserId = userIdInt; await _followUpDataService.UpdateAsync(followUp); return MapToDTO(followUp); } public async Task DeleteFollowUpAsync(int id, string userId) { var followUp = await _followUpDataService.GetByIdAsync(id); if (followUp == null) throw new InvalidOperationException($"Follow-Up with ID {id} not found"); followUp.IsDeleted = true; followUp.DeleterUserId = userId; followUp.DeletionTime = DateTime.UtcNow; await _followUpDataService.UpdateAsync(followUp); } public async Task FollowUpExistsAsync(int id) { return await _followUpDataService.ExistsAsync(id); } public async Task GetTotalFollowUpCountAsync() { return await _followUpDataService.CountAsync(); } public async Task> GetFollowUpListAsync( int page, int pageSize, string? search, string? status, CancellationToken cancellationToken) { status = string.IsNullOrWhiteSpace(status) ? "Open" : status; var items = await _followUpDataService.GetListPagedAsync(page, pageSize, search, status, cancellationToken); var totalCount = await _followUpDataService.GetListTotalAsync(search, status, cancellationToken); return new PagedResult { Items = items.Select(MapToListRow).ToList(), TotalCount = totalCount, Page = page, PageSize = pageSize }; } public async Task GetFollowUpDetailAsync(int id, CancellationToken cancellationToken) { var followUp = await _followUpDataService.GetDetailByIdAsync(id, cancellationToken); if (followUp == null) return null; var createdByName = await _followUpDataService.GetUserNameAsync(followUp.createdby, cancellationToken); return new FollowUpDetailDTO { Id = followUp.Id, Reason = followUp.Reason, ScheduleDate = followUp.ScheduleDate, ScheduleStartTime = followUp.ScheduleStartTime, EmployeeId = followUp.EmployeeId, WorkOrderId = followUp.WorkOrderId, AccountId = followUp.AccountId, LocationId = followUp.LocationId, AccountName = followUp.Account?.Name ?? "", AssignedTo = followUp.Employee != null ? $"{followUp.Employee.FirstName} {followUp.Employee.LastName}" : "", LocationName = followUp.Location?.Name ?? "", WorkOrderNumber = "", InternalWONumber = "", Status = followUp.Status, CreatedDate = followUp.CreatedDate, CreatedById = followUp.createdby, CreatedByName = createdByName }; } public async Task CreateOpenFollowUpAsync(FollowUpCreateRequestDTO dto, string userId, CancellationToken cancellationToken) { var followUp = new FollowUps { Reason = dto.Reason, ScheduleDate = dto.ScheduleDate, ScheduleStartTime = dto.ScheduleStartTime, EmployeeId = dto.EmployeeId, WorkOrderId = dto.WorkOrderId, AccountId = dto.AccountId, LocationId = dto.LocationId, Status = "Open", createdby = userId }; var created = await _followUpDataService.AddAsync(followUp, cancellationToken); return created.Id; } public async Task UpdateFollowUpFieldsAsync(int id, FollowUpUpdateRequestDTO dto, CancellationToken cancellationToken) { var followUp = await _followUpDataService.GetByIdForUpdateAsync(id, cancellationToken); if (followUp == null) throw new KeyNotFoundException($"Follow-Up with ID {id} not found"); followUp.Reason = dto.Reason; followUp.ScheduleDate = dto.ScheduleDate; followUp.ScheduleStartTime = dto.ScheduleStartTime; followUp.EmployeeId = dto.EmployeeId; followUp.WorkOrderId = dto.WorkOrderId; followUp.AccountId = dto.AccountId; followUp.LocationId = dto.LocationId; await _followUpDataService.UpdateAsync(followUp, cancellationToken); } public Task SetFollowUpStatusAsync(int id, string status, CancellationToken cancellationToken) { return _followUpDataService.SetStatusAsync(id, status, cancellationToken); } public Task RemoveFollowUpAsync(int id, CancellationToken cancellationToken) { return _followUpDataService.RemoveByIdAsync(id, cancellationToken); } private static FollowUpListRowDTO MapToListRow(FollowUps followUp) { return new FollowUpListRowDTO { Id = followUp.Id, Reason = followUp.Reason, ScheduleDate = followUp.ScheduleDate, ScheduleStartTime = followUp.ScheduleStartTime, EmployeeId = followUp.EmployeeId, WorkOrderId = followUp.WorkOrderId, AccountId = followUp.AccountId, LocationId = followUp.LocationId, AccountName = followUp.Account?.Name ?? "", AssignedTo = followUp.Employee != null ? $"{followUp.Employee.FirstName} {followUp.Employee.LastName}" : "", LocationName = followUp.Location?.Name ?? "", WorkOrderNumber = "", InternalWONumber = "", Status = followUp.Status, CreatedDate = followUp.CreatedDate, CreatedById = null, CreatedByName = "" }; } private FollowUpDTO MapToDTO(FollowUps followUp) { return new FollowUpDTO { Id = followUp.Id, Reason = followUp.Reason, ScheduleDate = followUp.ScheduleDate, ScheduleStartTime = followUp.ScheduleStartTime, Status = followUp.Status, EmployeeId = followUp.EmployeeId, EmployeeName = followUp.Employee != null ? $"{followUp.Employee.FirstName} {followUp.Employee.LastName}" : null, WorkOrderId = followUp.WorkOrderId, AccountId = followUp.AccountId, AccountName = followUp.Account?.Name, LocationId = followUp.LocationId, LocationName = followUp.Location?.Name, CreatedDate = followUp.CreatedDate }; } } }