using Data.SeaHavenIndustries; using Data.SeaHavenIndustries.Enums; using FluentValidation; using SeaHaven.DataServices.Interfaces; using SeaHaven.Services.DTOs; using SeaHaven.Services.Interfaces; using SeaHaven.Services.Validation; namespace SeaHaven.Services.Implementation { public class WorkOrderService : IWorkOrderService { private readonly IWorkOrderDataService _workOrderDataService; private readonly ICreateWorkOrderValidation _createValidator; private readonly IUpdateWorkOrderValidation _updateValidator; public WorkOrderService( IWorkOrderDataService workOrderDataService, ICreateWorkOrderValidation createValidator, IUpdateWorkOrderValidation updateValidator) { _workOrderDataService = workOrderDataService; _createValidator = createValidator; _updateValidator = updateValidator; } public async Task GetWorkOrderByIdAsync(int id) { var workOrder = await _workOrderDataService.GetByIdAsync(id); return workOrder == null ? null : WorkOrderDTO.MapToModel(workOrder); } public async Task GetWorkOrderByIdWithDetailsAsync(int id) { var workOrder = await _workOrderDataService.GetByIdWithDetailsAsync(id); return workOrder == null ? null : WorkOrderDTO.MapToModel(workOrder); } public async Task> GetAllWorkOrdersAsync() { var workOrders = await _workOrderDataService.GetAllAsync(); return workOrders.Select(WorkOrderDTO.MapToModel); } public async Task> GetWorkOrdersPagedAsync(int page, int pageSize, string? search = null, string? status = null, string? priority = null) { var (items, totalCount) = await _workOrderDataService.GetPagedAsync(page, pageSize, search, status, priority); return new PagedResult { Items = items.Select(WorkOrderDTO.MapToModel), TotalCount = totalCount, Page = page, PageSize = pageSize }; } public async Task CreateWorkOrderAsync(CreateWorkOrderDTO dto, string userId) { var validationResult = await _createValidator.ValidateAsync(dto); if (!validationResult.IsValid) { throw new ValidationException(validationResult.Errors); } var workOrder = CreateWorkOrderDTO.MapToEntity(dto); workOrder.createdby = userId; workOrder.CreatedDate = DateTime.UtcNow; workOrder.InternalWONumber = await _workOrderDataService.GenerateNextInternalWONumberAsync(); var saved = await _workOrderDataService.AddAsync(workOrder); await LogAuditAsync(saved.Id, userId, AuditAction.Create, "Work order created"); return saved.Id; } public async Task UpdateWorkOrderAsync(int id, UpdateWorkOrderDTO dto, string userId) { var validationResult = await _updateValidator.ValidateAsync(dto); if (!validationResult.IsValid) { throw new ValidationException(validationResult.Errors); } var existingWorkOrder = await _workOrderDataService.GetByIdAsync(id); if (existingWorkOrder == null) return false; var changes = new List(); changes.AddRange(TrackChanges(existingWorkOrder, dto)); UpdateWorkOrderDTO.UpdateEntity(dto, existingWorkOrder); await _workOrderDataService.UpdateAsync(existingWorkOrder); if (changes.Any()) { await LogAuditAsync(id, userId, AuditAction.Edit, string.Join(", ", changes)); } return true; } public async Task DeleteWorkOrderAsync(int id, string userId) { if (!await _workOrderDataService.ExistsAsync(id)) return false; await _workOrderDataService.DeleteWorkOrderAttachmentsAsync(id); await _workOrderDataService.DeleteWorkOrderContactsAsync(id); await _workOrderDataService.DeleteWorkOrderCategoriesAsync(id); await _workOrderDataService.DeleteAsync(id); await LogAuditAsync(id, userId, AuditAction.Delete, "Work order deleted"); return true; } public async Task WorkOrderExistsAsync(int id) { return await _workOrderDataService.ExistsAsync(id); } public async Task GenerateNextInternalWONumberAsync() { return await _workOrderDataService.GenerateNextInternalWONumberAsync(); } public async Task GetTotalWorkOrderCountAsync() { return await _workOrderDataService.CountAsync(); } private List TrackChanges(WorkOrder existing, UpdateWorkOrderDTO dto) { var changes = new List(); if (dto.WorkerOrderTitle != null && dto.WorkerOrderTitle != existing.WorkerOrderTitle) changes.Add($"Title: {existing.WorkerOrderTitle} → {dto.WorkerOrderTitle}"); if (dto.Status.HasValue && dto.Status.ToString() != existing.Status) changes.Add($"Status: {existing.Status} → {dto.Status}"); if (dto.Priority.HasValue && dto.Priority.ToString() != existing.Priority) changes.Add($"Priority: {existing.Priority} → {dto.Priority}"); if (dto.AssignTo != null && dto.AssignTo != existing.AssignTo) changes.Add($"Assigned To: {existing.AssignTo} → {dto.AssignTo}"); if (dto.DueDate.HasValue && dto.DueDate != existing.DueDate) changes.Add($"Due Date: {existing.DueDate:yyyy-MM-dd} → {dto.DueDate:yyyy-MM-dd}"); return changes; } private async Task LogAuditAsync(int workOrderId, string userId, AuditAction action, string description) { var auditLog = new WorkOrderAuditLog { WorkOrderId = workOrderId, Action = action.ToString(), FieldName = description, UserId = userId, CreatedAt = DateTime.UtcNow }; await _workOrderDataService.AddAuditLogAsync(auditLog); } } }