using Api.SeaHavenIndustries.Helper; using Data.SeaHavenIndustries; using FluentValidation; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Logging; using SeaHaven.DataServices.Models; using SeaHaven.Services.DTOs; using SeaHaven.Services.Interfaces; using System.Security.Claims; namespace Api.SeaHavenIndustries.Controllers { [Authorize] [ApiController] [Route("api/vendor-company-roster")] public class VendorCompanyRosterController : Controller { private readonly IVendorCompanyRosterService _rosterService; private readonly ILogger _logger; public VendorCompanyRosterController( IVendorCompanyRosterService rosterService, ILogger logger) { _rosterService = rosterService; _logger = logger; } [HttpGet] public async Task Get( [FromQuery] int? vendorId, [FromQuery] int? companyId, CancellationToken cancellationToken) { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); if (userId == null) return Unauthorized(new Response { Status = "Error", Message = "User not authenticated" }); try { var roster = await _rosterService.GetRosterAsync(vendorId, companyId, userId, cancellationToken); if (roster == null) return NotFound(new Response { Status = "Error", Message = "Vendor roster not found" }); return Ok(roster); } catch (ValidationException vex) { var errors = string.Join(", ", vex.Errors.Select(e => e.ErrorMessage)); return BadRequest(new Response { Status = "Validation Error", Message = errors }); } catch (UnauthorizedAccessException) { return Unauthorized(new Response { Status = "Error", Message = "User not authenticated" }); } catch (Exception ex) { return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpPost] public async Task Create([FromBody] CreateVendorRosterDTO model, CancellationToken cancellationToken) { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); if (userId == null) return Unauthorized(new Response { Status = "Error", Message = "User not authenticated" }); try { var roster = await _rosterService.CreateRosterAsync(model, userId, cancellationToken); return Ok(roster); } catch (ValidationException vex) { var errors = string.Join(", ", vex.Errors.Select(e => e.ErrorMessage)); return BadRequest(new Response { Status = "Validation Error", Message = errors }); } catch (UnauthorizedAccessException) { return Unauthorized(new Response { Status = "Error", Message = "User not authenticated" }); } catch (Exception ex) { return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } [HttpPut("{companyId:int}")] public async Task Reconcile( int companyId, [FromBody] ReconcileVendorRosterDTO model, CancellationToken cancellationToken) { var userId = User.FindFirstValue(ClaimTypes.NameIdentifier); if (userId == null) return Unauthorized(new Response { Status = "Error", Message = "User not authenticated" }); try { var roster = await _rosterService.ReconcileRosterAsync(companyId, model, userId, cancellationToken); return Ok(roster); } catch (ValidationException vex) { var errors = string.Join(", ", vex.Errors.Select(e => e.ErrorMessage)); return BadRequest(new Response { Status = "Validation Error", Message = errors }); } catch (UnauthorizedAccessException) { return Unauthorized(new Response { Status = "Error", Message = "User not authenticated" }); } catch (KeyNotFoundException) { return NotFound(new Response { Status = "Error", Message = "Vendor company not found" }); } catch (VendorRosterConflictException conflict) { return Conflict(new { Status = "Conflict", Message = _logger.Sanitize(conflict, "Vendor roster changes conflict with open work orders"), BlockedWorkOrders = conflict.BlockedWorkOrders }); } catch (DbUpdateConcurrencyException) { return Conflict(new { Status = "Conflict", Message = "The vendor company was modified by another user. Refresh and retry.", Code = 409 }); } catch (Exception ex) { return StatusCode(500, new Response { Status = "Error", Message = _logger.Sanitize(ex) }); } } } }