using GestionIntegral.Api.Dtos.Usuarios; using GestionIntegral.Api.Services.Usuarios; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; namespace GestionIntegral.Api.Controllers.Usuarios { [Route("api/[controller]")] [ApiController] [Authorize] // Requiere autenticación general public class UsuariosController : ControllerBase { private readonly IUsuarioService _usuarioService; private readonly ILogger _logger; // Permisos para gestión de usuarios (CU001-CU004) private const string PermisoVerUsuarios = "CU001"; private const string PermisoAgregarUsuarios = "CU002"; private const string PermisoModificarUsuarios = "CU003"; // Asumo que CU003 es para modificar, aunque el Excel dice "Eliminar" private const string PermisoAsignarPerfil = "CU004"; // Este se relaciona con la edición del perfil del usuario public UsuariosController(IUsuarioService usuarioService, ILogger logger) { _usuarioService = usuarioService; _logger = logger; } private bool TienePermiso(string codAccRequerido) { if (User.IsInRole("SuperAdmin")) return true; return User.HasClaim(c => c.Type == "permission" && c.Value == codAccRequerido); } private int? GetCurrentUserId() { var userIdClaim = User.FindFirstValue(ClaimTypes.NameIdentifier) ?? User.FindFirstValue("sub"); if (int.TryParse(userIdClaim, out int userId)) return userId; _logger.LogWarning("No se pudo obtener el UserId del token JWT en UsuariosController."); return null; } // GET: api/usuarios [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task GetAllUsuarios([FromQuery] string? user, [FromQuery] string? nombre) { if (!TienePermiso(PermisoVerUsuarios)) return Forbid(); var usuarios = await _usuarioService.ObtenerTodosAsync(user, nombre); return Ok(usuarios); } // GET: api/usuarios/{id} [HttpGet("{id:int}", Name = "GetUsuarioById")] [ProducesResponseType(typeof(UsuarioDto), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task GetUsuarioById(int id) { if (!TienePermiso(PermisoVerUsuarios)) return Forbid(); var usuario = await _usuarioService.ObtenerPorIdAsync(id); if (usuario == null) return NotFound(); return Ok(usuario); } // POST: api/usuarios [HttpPost] [ProducesResponseType(typeof(UsuarioDto), StatusCodes.Status201Created)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task CreateUsuario([FromBody] CreateUsuarioRequestDto createDto) { if (!TienePermiso(PermisoAgregarUsuarios)) return Forbid(); if (!ModelState.IsValid) return BadRequest(ModelState); var idUsuarioCreador = GetCurrentUserId(); if (idUsuarioCreador == null) return Unauthorized("Token inválido."); var (usuarioCreado, error) = await _usuarioService.CrearAsync(createDto, idUsuarioCreador.Value); if (error != null) return BadRequest(new { message = error }); if (usuarioCreado == null) return StatusCode(StatusCodes.Status500InternalServerError, "Error al crear el usuario."); return CreatedAtRoute("GetUsuarioById", new { id = usuarioCreado.Id }, usuarioCreado); } // PUT: api/usuarios/{id} [HttpPut("{id:int}")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] // CU003 o CU004 [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task UpdateUsuario(int id, [FromBody] UpdateUsuarioRequestDto updateDto) { // Modificar datos básicos (CU003), reasignar perfil (CU004) if (!TienePermiso(PermisoModificarUsuarios) && !TienePermiso(PermisoAsignarPerfil)) return Forbid(); if (!ModelState.IsValid) return BadRequest(ModelState); var idUsuarioModificador = GetCurrentUserId(); if (idUsuarioModificador == null) return Unauthorized("Token inválido."); var (exito, error) = await _usuarioService.ActualizarAsync(id, updateDto, idUsuarioModificador.Value); if (!exito) { if (error == "Usuario no encontrado.") return NotFound(new { message = error }); return BadRequest(new { message = error }); } return NoContent(); } // POST: api/usuarios/{id}/set-password [HttpPost("{id:int}/set-password")] [Authorize(Roles = "SuperAdmin")] // Solo SuperAdmin puede resetear claves directamente [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task SetPassword(int id, [FromBody] SetPasswordRequestDto setPasswordDto) { if (!ModelState.IsValid) return BadRequest(ModelState); var idAdmin = GetCurrentUserId(); if (idAdmin == null) return Unauthorized("Token inválido."); var (exito, error) = await _usuarioService.SetPasswordAsync(id, setPasswordDto, idAdmin.Value); if (!exito) { if (error == "Usuario no encontrado.") return NotFound(new { message = error }); return BadRequest(new { message = error }); } return NoContent(); } // POST: api/usuarios/{id}/toggle-habilitado [HttpPost("{id:int}/toggle-habilitado")] [ProducesResponseType(StatusCodes.Status204NoContent)] [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] // Podría ser PermisoModificarUsuarios (CU003) [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task ToggleHabilitado(int id, [FromBody] bool habilitar) { if (!TienePermiso(PermisoModificarUsuarios)) return Forbid(); var idAdmin = GetCurrentUserId(); if (idAdmin == null) return Unauthorized("Token inválido."); var (exito, error) = await _usuarioService.CambiarEstadoHabilitadoAsync(id, habilitar, idAdmin.Value); if (!exito) { if (error == "Usuario no encontrado.") return NotFound(new { message = error }); return BadRequest(new { message = error }); } return NoContent(); } } }