using Api.SeaHavenIndustries.DTOs; using Api.SeaHavenIndustries.Helper; using Data.SeaHavenIndustries; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using SeaHaven.Services.DTOs; using SeaHaven.Services.Exceptions; using SeaHaven.Services.Interfaces; using System.Security.Claims; namespace Api.SeaHavenIndustries.Controllers { [Authorize] [ApiController] [Route("api/WorkOrder")] [Route("api/workorders")] public class WorkOrderDetailController : Controller { private readonly IWorkOrderDetailService _workOrderDetailService; private readonly IWorkOrderCommentService _workOrderCommentService; private readonly IWorkOrderUpliftService _workOrderUpliftService; private readonly ILogger _logger; public WorkOrderDetailController( IWorkOrderDetailService workOrderDetailService, IWorkOrderCommentService workOrderCommentService, IWorkOrderUpliftService workOrderUpliftService, ILogger logger) { _workOrderDetailService = workOrderDetailService; _workOrderCommentService = workOrderCommentService; _workOrderUpliftService = workOrderUpliftService; _logger = logger; } [HttpGet("{id:int}/detail")] public async Task GetDetail(int id) { try { var detail = await _workOrderDetailService.GetDetailAsync(id, User); if (detail == null) return NotFound(new Response { Status = "Error", Message = "Work order not found." }); return Ok(detail); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden") { return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = ex.Message }); } } [HttpGet("{id:int}/audit")] public async Task GetAudit(int id, [FromQuery] int limit = 50) { try { var audit = await _workOrderDetailService.GetAuditAsync(id, User, limit); if (audit == null) return NotFound(new Response { Status = "Error", Message = "Work order not found." }); return Ok(audit); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden") { return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = ex.Message }); } } [HttpGet("{id:int}/comments")] public async Task GetBoardComments(int id) { try { var comments = await _workOrderCommentService.GetCommentsAsync(id, User); if (comments == null) return NotFound(new Response { Status = "Error", Message = "Work order not found." }); return Ok(comments); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden") { return StatusCode(StatusCodes.Status403Forbidden, new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message }); } } [HttpPost("{id:int}/comments")] public async Task AddBoardComment(int id, [FromBody] WorkOrderCommentCreateDto request) { try { var actorId = User.FindFirstValue(ClaimTypes.NameIdentifier); var comment = await _workOrderCommentService.AddCommentAsync(id, request, User, actorId); return Ok(comment); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "NotFound") { return NotFound(new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message }); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden") { return StatusCode(StatusCodes.Status403Forbidden, new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message }); } catch (WorkOrderBoardValidationException ex) { return UnprocessableEntity(new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message }); } } [HttpPatch("{id:int}/comments/{commentId:int}")] public async Task UpdateBoardComment( int id, int commentId, [FromBody] WorkOrderCommentCreateDto request) { try { var actorId = User.FindFirstValue(ClaimTypes.NameIdentifier); var comment = await _workOrderCommentService.UpdateCommentAsync( id, commentId, request, User, actorId); return Ok(comment); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "NotFound") { return NotFound(new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message }); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden") { return StatusCode(StatusCodes.Status403Forbidden, new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message }); } catch (WorkOrderBoardValidationException ex) { return UnprocessableEntity(new WorkOrderBoardValidationErrorDto { Code = ex.Code, Message = ex.Message }); } } [HttpGet("{id:int}/uplifts")] public async Task ListUplifts(int id, CancellationToken cancellationToken) { try { var items = await _workOrderUpliftService.ListAsync(id, User, cancellationToken); if (items == null) return NotFound(new Response { Status = "Error", Message = "Work order not found." }); return Ok(new DataResponse { Status = "Success", Data = new WorkOrderUpliftListDto { Items = items.ToList() } }); } catch (WorkOrderBoardValidationException ex) when (ex.Code == "Forbidden") { return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = ex.Message }); } } [HttpPost("{id:int}/uplifts")] public async Task CreateUplift( int id, [FromBody] CreateWorkOrderUpliftRequestDto request, CancellationToken cancellationToken) { try { var created = await _workOrderUpliftService.CreateAsync(id, request, User, cancellationToken); if (created == null) return NotFound(new Response { Status = "Error", Message = "Work order not found." }); return Ok(new DataResponse { Status = "Success", Data = created }); } catch (KeyNotFoundException ex) { return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Resource not found") }); } catch (UpliftForbiddenException ex) { return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = _logger.Sanitize(ex, "You are not authorized to perform this action") }); } catch (InvalidOperationException ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The uplift request could not be created") }); } } [HttpPost("{id:int}/uplifts/{upliftId:int}/cancel")] public async Task CancelUplift(int id, int upliftId, CancellationToken cancellationToken) { try { var cancelled = await _workOrderUpliftService.CancelAsync(id, upliftId, User, cancellationToken); if (cancelled == null) return NotFound(new Response { Status = "Error", Message = "Work order not found." }); return Ok(new DataResponse { Status = "Success", Data = cancelled }); } catch (KeyNotFoundException ex) { return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Uplift request not found") }); } catch (UpliftForbiddenException ex) { return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = _logger.Sanitize(ex, "You are not authorized to perform this action") }); } catch (InvalidOperationException ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The uplift request cannot be cancelled in its current state") }); } } [HttpPost("{id:int}/uplifts/{upliftId:int}/revoke")] public async Task RevokeUplift( int id, int upliftId, [FromBody] RevokeWorkOrderUpliftRequestDto? request, CancellationToken cancellationToken) { try { var revoked = await _workOrderUpliftService.RevokeAsync( id, upliftId, request ?? new RevokeWorkOrderUpliftRequestDto(), User, cancellationToken); if (revoked == null) return NotFound(new Response { Status = "Error", Message = "Work order not found." }); return Ok(new DataResponse { Status = "Success", Data = revoked }); } catch (KeyNotFoundException ex) { return NotFound(new Response { Status = "Error", Message = _logger.Sanitize(ex, "Uplift request not found") }); } catch (UpliftForbiddenException ex) { return StatusCode(StatusCodes.Status403Forbidden, new Response { Status = "Error", Message = _logger.Sanitize(ex, "You are not authorized to perform this action") }); } catch (InvalidOperationException ex) { return BadRequest(new Response { Status = "Error", Message = _logger.Sanitize(ex, "The uplift request cannot be revoked in its current state") }); } } } }