using GestionIntegral.Api.Dtos.Contables; using GestionIntegral.Api.Services.Contables; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks; namespace GestionIntegral.Api.Controllers.Contables { [Route("api/saldos")] [ApiController] [Authorize] // Requiere autenticación para todos los endpoints public class SaldosController : ControllerBase { private readonly ISaldoService _saldoService; private readonly ILogger _logger; // Define un permiso específico para ver saldos, y otro para ajustarlos (SuperAdmin implícito) private const string PermisoVerSaldos = "CS001"; // Ejemplo: Cuentas Saldos Ver private const string PermisoAjustarSaldos = "CS002"; // Ejemplo: Cuentas Saldos Ajustar (o solo SuperAdmin) public SaldosController(ISaldoService saldoService, ILogger logger) { _saldoService = saldoService; _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() { 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 SaldosController."); return null; } // GET: api/saldos [HttpGet] [ProducesResponseType(typeof(IEnumerable), StatusCodes.Status200OK)] [ProducesResponseType(StatusCodes.Status403Forbidden)] public async Task GetSaldosGestion( [FromQuery] string? destino, [FromQuery] int? idDestino, [FromQuery] int? idEmpresa) { if (!TienePermiso(PermisoVerSaldos)) // Usar el nuevo permiso { _logger.LogWarning("Acceso denegado a GetSaldosGestion para Usuario ID {userId}", GetCurrentUserId() ?? 0); return Forbid(); } try { var saldos = await _saldoService.ObtenerSaldosParaGestionAsync(destino, idDestino, idEmpresa); return Ok(saldos); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener saldos para gestión."); return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al obtener saldos."); } } // POST: api/saldos/ajustar [HttpPost("ajustar")] [ProducesResponseType(typeof(SaldoGestionDto), StatusCodes.Status200OK)] // Devuelve el saldo actualizado [ProducesResponseType(StatusCodes.Status400BadRequest)] [ProducesResponseType(StatusCodes.Status403Forbidden)] // Solo SuperAdmin o con permiso específico [ProducesResponseType(StatusCodes.Status404NotFound)] public async Task AjustarSaldoManualmente([FromBody] AjusteSaldoRequestDto ajusteDto) { // Esta operación debería ser MUY restringida. Solo SuperAdmin o un permiso muy específico. if (!User.IsInRole("SuperAdmin") && !TienePermiso(PermisoAjustarSaldos)) { _logger.LogWarning("Intento no autorizado de ajustar saldo por Usuario ID {userId}", GetCurrentUserId() ?? 0); return Forbid("No tiene permisos para realizar ajustes manuales de saldo."); } if (!ModelState.IsValid) return BadRequest(ModelState); var idUsuario = GetCurrentUserId(); if (idUsuario == null) return Unauthorized("No se pudo identificar al usuario."); try { var (exito, error, saldoActualizado) = await _saldoService.RealizarAjusteManualSaldoAsync(ajusteDto, idUsuario.Value); if (!exito) { if (error != null && error.Contains("No se encontró un saldo existente")) return NotFound(new { message = error }); return BadRequest(new { message = error ?? "Error desconocido al ajustar el saldo." }); } return Ok(saldoActualizado); } catch (Exception ex) { _logger.LogError(ex, "Error crítico al ajustar saldo manualmente."); return StatusCode(StatusCodes.Status500InternalServerError, "Error interno al procesar el ajuste de saldo."); } } } }