using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using vendorApproverBackend.Entities; using vendorApproverBackend.Enums; using vendorApproverBackend.Requests; using vendorApproverBackend.Services; using vendorApproverBackend.Interfaces; using System.Security.Claims; using vendorApproverBackend.Responses; namespace vendorApproverBackend.Controllers { [ApiController] [Route("api/employee-applications")] public class EmployeeApplicationController : ControllerBase { private readonly UserService _userService; private readonly EmployeeApplicationService _applicationService; private readonly IEmailService _emailService; private readonly ILogger _logger; public EmployeeApplicationController(UserService userService , IEmailService emailService ,EmployeeApplicationService applicationService, ILogger logger) { _applicationService = applicationService; _userService = userService; _emailService = emailService; _logger = logger; } [HttpPost("add-application/{userId}")] [ProducesResponseType(StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Roles = "ADMIN,EMPLOYEE,VENDOR,FINANCIAL")] public async Task AddApplicationByEmployee(long userId, [FromBody] CreateEmployeeApplicationRequest request) { if (!ModelState.IsValid) { return BadRequest(ModelState); } try { var newApplication = await _applicationService.CreateApplicationAsync(userId, request); return CreatedAtAction(nameof(FindApplicationById), new { applicationId = newApplication.Id }, newApplication); } catch (KeyNotFoundException ex) { _logger.LogWarning(ex, "Attempted to add application for non-existent User ID: {UserId}", userId); return NotFound(ex.Message); } catch (Exception ex) { _logger.LogError(ex, "Error creating employee application for user {UserId}", userId); return StatusCode(StatusCodes.Status500InternalServerError, "Failed to create application due to an internal error."); } } [HttpPut("update/{applicationId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Roles = "ADMIN,EMPLOYEE,VENDOR,FINANCIAL")] public async Task UpdateApplication(long applicationId, [FromBody] CreateEmployeeApplicationRequest request) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var updatedApplication = await _applicationService.UpdateApplicationAsync(applicationId, request); if (updatedApplication == null) { return NotFound($"Application ID {applicationId} not found or cannot be updated (e.g., already approved)."); } return Ok(updatedApplication); } [HttpDelete("delete/{applicationId}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Roles = "ADMIN,EMPLOYEE,VENDOR,FINANCIAL")] public async Task DeleteApplication(long applicationId) { var result = await _applicationService.DeleteApplicationAsync(applicationId); if (!result) { return NotFound($"Application ID {applicationId} not found."); } return NoContent(); } [HttpGet("application-by-id/{applicationId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [Authorize(Roles = "ADMIN,EMPLOYEE,VENDOR,FINANCIAL")] public async Task FindApplicationById(long applicationId) { var application = await _applicationService.FindByIdAsync(applicationId); if (application == null) { return NotFound($"Application ID {applicationId} not found."); } return Ok(application); } [HttpPatch("update-application-status/{applicationId}")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status404NotFound)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [Authorize(Roles = "ADMIN,EMPLOYEE,VENDOR,FINANCIAL")] public async Task UpdateApplicationStatus(long applicationId, [FromBody] UpdateApplicationStatusRequest request) { var updatedApplication = await _applicationService.UpdateApplicationStatusAsync(applicationId, request); if (updatedApplication == null) { return NotFound($"Application ID {applicationId} not found."); } return Ok(updatedApplication); } [HttpGet("get-applications")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [Authorize(Roles = "ADMIN,EMPLOYEE,VENDOR,FINANCIAL")] public async Task>> GetAllApplicationsForAdmin( [FromQuery] int page = 0, [FromQuery] int size = 5, [FromQuery] long? userId = null, [FromQuery] ApplicationStatus? status = null, [FromQuery] EmployeeTypeEnum? type = null, [FromQuery] DateTime? submissionDate = null, [FromQuery] string? name = null) { if (page < 0 || size <= 0) { return BadRequest("Page must be non-negative and Size must be positive."); } var result = await _applicationService.GetApplicationsByCriteriaAsync( page, size, userId, status, type, submissionDate?.Date, name); return Ok(result); } [HttpGet("get-my-applications")] [ProducesResponseType(StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [Authorize(Roles = "EMPLOYEE")] public async Task>> GetAllApplicationsEmployee( [FromQuery] int page = 0, [FromQuery] int size = 5, [FromQuery] ApplicationStatus? status = null, [FromQuery] EmployeeTypeEnum? type = null, [FromQuery] DateTime? submissionDate = null) { var username = User.FindFirstValue(ClaimTypes.Name); if (string.IsNullOrEmpty(username)) { return Unauthorized("Username claim not found in token."); } var user = await _userService.FindByUsernameAsync(username); if (user == null) { return NotFound("User not found."); } if (page < 0 || size <= 0) { return BadRequest("Page must be non-negative and Size must be positive."); } var result = await _applicationService.GetApplicationsByCriteriaAsync( page, size, user.Id, status, type, submissionDate?.Date, null); return Ok(result); } } }