using GestionIntegral.Api.Data; using GestionIntegral.Api.Data.Repositories.Impresion; using GestionIntegral.Api.Dtos.Auditoria; using GestionIntegral.Api.Dtos.Impresion; using GestionIntegral.Api.Models.Impresion; using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.Data; using System.Linq; using System.Threading.Tasks; namespace GestionIntegral.Api.Services.Impresion { public class EstadoBobinaService : IEstadoBobinaService { private readonly IEstadoBobinaRepository _estadoBobinaRepository; private readonly DbConnectionFactory _connectionFactory; private readonly ILogger _logger; public EstadoBobinaService(IEstadoBobinaRepository estadoBobinaRepository, DbConnectionFactory connectionFactory, ILogger logger) { _estadoBobinaRepository = estadoBobinaRepository; _connectionFactory = connectionFactory; _logger = logger; } private EstadoBobinaDto MapToDto(EstadoBobina estadoBobina) => new EstadoBobinaDto { IdEstadoBobina = estadoBobina.IdEstadoBobina, Denominacion = estadoBobina.Denominacion, Obs = estadoBobina.Obs }; public async Task> ObtenerTodosAsync(string? denominacionFilter) { var estadosBobina = await _estadoBobinaRepository.GetAllAsync(denominacionFilter); return estadosBobina.Select(MapToDto); } public async Task> ObtenerTodosDropdownAsync() { var estadosBobina = await _estadoBobinaRepository.GetAllDropdownAsync(); return estadosBobina; } public async Task ObtenerPorIdAsync(int id) { var estadoBobina = await _estadoBobinaRepository.GetByIdAsync(id); return estadoBobina == null ? null : MapToDto(estadoBobina); } public async Task<(EstadoBobinaDto? EstadoBobina, string? Error)> CrearAsync(CreateEstadoBobinaDto createDto, int idUsuario) { if (await _estadoBobinaRepository.ExistsByDenominacionAsync(createDto.Denominacion)) { return (null, "La denominación del estado de bobina ya existe."); } var nuevoEstado = new EstadoBobina { Denominacion = createDto.Denominacion, Obs = createDto.Obs }; using var connection = _connectionFactory.CreateConnection(); if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); try { var estadoCreado = await _estadoBobinaRepository.CreateAsync(nuevoEstado, idUsuario, transaction); if (estadoCreado == null) throw new DataException("La creación en el repositorio devolvió null."); transaction.Commit(); // Síncrono _logger.LogInformation("EstadoBobina ID {IdEstadoBobina} creado por Usuario ID {IdUsuario}.", estadoCreado.IdEstadoBobina, idUsuario); return (MapToDto(estadoCreado), null); } catch (Exception ex) { try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error rollback CrearAsync EstadoBobina."); } _logger.LogError(ex, "Error CrearAsync EstadoBobina. Denominación: {Denominacion}", createDto.Denominacion); return (null, $"Error interno al crear el estado de bobina: {ex.Message}"); } } public async Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdateEstadoBobinaDto updateDto, int idUsuario) { if (await _estadoBobinaRepository.ExistsByDenominacionAsync(updateDto.Denominacion, id)) { return (false, "La denominación del estado de bobina ya existe para otro registro."); } var estadoAActualizar = new EstadoBobina { IdEstadoBobina = id, Denominacion = updateDto.Denominacion, Obs = updateDto.Obs }; using var connection = _connectionFactory.CreateConnection(); if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); try { var actualizado = await _estadoBobinaRepository.UpdateAsync(estadoAActualizar, idUsuario, transaction); if (!actualizado) throw new DataException("La operación de actualización no afectó ninguna fila."); transaction.Commit(); // Síncrono _logger.LogInformation("EstadoBobina ID {IdEstadoBobina} actualizado por Usuario ID {IdUsuario}.", id, idUsuario); return (true, null); } catch (KeyNotFoundException knfex) { try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error rollback ActualizarAsync EstadoBobina."); } _logger.LogWarning(knfex, "Intento de actualizar EstadoBobina ID: {Id} no encontrado.", id); return (false, "Estado de bobina no encontrado."); } catch (Exception ex) { try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error rollback ActualizarAsync EstadoBobina."); } _logger.LogError(ex, "Error ActualizarAsync EstadoBobina ID: {Id}", id); return (false, $"Error interno al actualizar el estado de bobina: {ex.Message}"); } } public async Task<(bool Exito, string? Error)> EliminarAsync(int id, int idUsuario) { // Estados "fijos" como Disponible (1), En Uso (2), Dañada (3) probablemente no deberían eliminarse. // Podrías añadir una validación aquí o en el repositorio si es necesario. if (id <= 3) // Asumiendo IDs fijos para los estados base { return (false, "Los estados base (Disponible, En Uso, Dañada) no se pueden eliminar."); } if (await _estadoBobinaRepository.IsInUseAsync(id)) { return (false, "No se puede eliminar. El estado de bobina está siendo utilizado en el stock."); } using var connection = _connectionFactory.CreateConnection(); if (connection is System.Data.Common.DbConnection dbConn) await dbConn.OpenAsync(); else connection.Open(); using var transaction = connection.BeginTransaction(IsolationLevel.ReadCommitted); try { var eliminado = await _estadoBobinaRepository.DeleteAsync(id, idUsuario, transaction); if (!eliminado) throw new DataException("La operación de eliminación no afectó ninguna fila."); transaction.Commit(); // Síncrono _logger.LogInformation("EstadoBobina ID {IdEstadoBobina} eliminado por Usuario ID {IdUsuario}.", id, idUsuario); return (true, null); } catch (KeyNotFoundException knfex) { try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error rollback EliminarAsync EstadoBobina."); } _logger.LogWarning(knfex, "Intento de eliminar EstadoBobina ID: {Id} no encontrado.", id); return (false, "Estado de bobina no encontrado."); } catch (Exception ex) { try { transaction.Rollback(); } catch (Exception rbEx) { _logger.LogError(rbEx, "Error rollback EliminarAsync EstadoBobina."); } _logger.LogError(ex, "Error EliminarAsync EstadoBobina ID: {Id}", id); return (false, $"Error interno al eliminar el estado de bobina: {ex.Message}"); } } public async Task> ObtenerHistorialAsync( DateTime? fechaDesde, DateTime? fechaHasta, int? idUsuarioModifico, string? tipoModificacion, int? idEstadoBobinaAfectado) { var historialData = await _estadoBobinaRepository.GetHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idEstadoBobinaAfectado); return historialData.Select(h => new EstadoBobinaHistorialDto { Id_EstadoBobina = h.Historial.Id_EstadoBobina, Denominacion = h.Historial.Denominacion, Obs = h.Historial.Obs, Id_Usuario = h.Historial.Id_Usuario, NombreUsuarioModifico = h.NombreUsuarioModifico, FechaMod = h.Historial.FechaMod, TipoMod = h.Historial.TipoMod }).ToList(); } } }