using GestionIntegral.Api.Dtos.Impresion; using GestionIntegral.Api.Services.Impresion; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; namespace GestionIntegral.Api.Controllers.Impresion { [Route("api/[controller]")] // Ruta base: /api/tiradas [ApiController] [Authorize] public class TiradasController : ControllerBase { private readonly ITiradaService _tiradaService; private readonly ILogger _logger; // Permisos para Tiradas (IT001 a IT003) private const string PermisoVerTiradas = "IT001"; private const string PermisoRegistrarTirada = "IT002"; private const string PermisoEliminarTirada = "IT003"; private const string PermisoModificarTirada = "IT004"; public TiradasController(ITiradaService tiradaService, ILogger logger) { _tiradaService = tiradaService; _logger = logger; } private bool TienePermiso(string codAcc) => User.IsInRole("SuperAdmin") || User.HasClaim(c => c.Type == "permission" && c.Value == codAcc); private int? GetCurrentUserId() { if (int.TryParse(User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub"), out int userId)) return userId; _logger.LogWarning("No se pudo obtener el UserId del token JWT en TiradasController."); return null; } // GET: api/tiradas [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task GetTiradas( [FromQuery] DateTime? fecha, [FromQuery] int? idPublicacion, [FromQuery] int? idPlanta) { if (!TienePermiso(PermisoVerTiradas)) return Forbid(); try { var tiradas = await _tiradaService.ObtenerTiradasAsync(fecha, idPublicacion, idPlanta); return Ok(tiradas); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener listado de tiradas."); return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al procesar la solicitud."); } } // POST: api/tiradas [HttpPost] [ProducesResponseType(typeof(TiradaDto), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task RegistrarTirada([FromBody] CreateTiradaRequestDto createDto) { if (!TienePermiso(PermisoRegistrarTirada)) return Forbid(); if (!ModelState.IsValid) return BadRequest(ModelState); var userId = GetCurrentUserId(); if (userId == null) return Unauthorized(); var (tiradaCreada, error) = await _tiradaService.RegistrarTiradaCompletaAsync(createDto, userId.Value); if (error != null) return BadRequest(new { message = error }); if (tiradaCreada == null) return StatusCode(StatusCodes.Status500InternalServerError, "Error al registrar la tirada."); // No hay un "GetById" simple para una tirada completa con un solo ID, // ya que se identifica por Fecha, Publicacion, Planta. // Podríamos devolver la tirada creada directamente. return StatusCode(StatusCodes.Status201Created, tiradaCreada); } [HttpPut] [ProducesResponseType(typeof(TiradaDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task ModificarTirada( [FromQuery, BindRequired] DateTime fecha, [FromQuery, BindRequired] int idPublicacion, [FromQuery, BindRequired] int idPlanta, [FromBody] UpdateTiradaRequestDto updateDto) { if (!TienePermiso(PermisoModificarTirada)) return Forbid(); if (!ModelState.IsValid) return BadRequest(ModelState); var userId = GetCurrentUserId(); if (userId == null) return Unauthorized(); var (tiradaActualizada, error) = await _tiradaService.ModificarTiradaCompletaAsync(fecha, idPublicacion, idPlanta, updateDto, userId.Value); if (error != null) { // Chequear si el error es porque no se encontró la tirada. if (error.StartsWith("No se encontró la tirada")) { return NotFound(new { message = error }); } return BadRequest(new { message = error }); } if (tiradaActualizada == null) { return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al modificar la tirada."); } return Ok(tiradaActualizada); } // DELETE: api/tiradas // Se identifica la tirada a eliminar por su combinación única de Fecha, IdPublicacion, IdPlanta [HttpDelete] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] // Si no se encuentra la tirada para borrar public async Task DeleteTirada( [FromQuery, BindRequired] DateTime fecha, // Microsoft.AspNetCore.Mvc.ModelBinding.BindRequiredAttribute [FromQuery, BindRequired] int idPublicacion, [FromQuery, BindRequired] int idPlanta) { if (!TienePermiso(PermisoEliminarTirada)) return Forbid(); var userId = GetCurrentUserId(); if (userId == null) return Unauthorized(); var (exito, error) = await _tiradaService.EliminarTiradaCompletaAsync(fecha, idPublicacion, idPlanta, userId.Value); if (!exito) { if (error == "No se encontró una tirada principal para los criterios especificados.") return NotFound(new { message = error }); return BadRequest(new { message = error }); } return NoContent(); } } }