using Dapper; using GestionIntegral.Api.Data.Repositories.Impresion; using GestionIntegral.Api.Models.Impresion; using Microsoft.Extensions.Logging; using System.Collections.Generic; using System.Data; using System.Linq; using System.Text; using System.Threading.Tasks; namespace GestionIntegral.Api.Data.Repositories.Impresion { public class EstadoBobinaRepository : IEstadoBobinaRepository { private readonly DbConnectionFactory _connectionFactory; private readonly ILogger _logger; public EstadoBobinaRepository(DbConnectionFactory connectionFactory, ILogger logger) { _connectionFactory = connectionFactory; _logger = logger; } public async Task> GetAllAsync(string? denominacionFilter) { var sqlBuilder = new StringBuilder("SELECT Id_EstadoBobina AS IdEstadoBobina, Denominacion, Obs FROM dbo.bob_dtEstadosBobinas WHERE 1=1"); var parameters = new DynamicParameters(); if (!string.IsNullOrWhiteSpace(denominacionFilter)) { sqlBuilder.Append(" AND Denominacion LIKE @DenominacionFilter"); parameters.Add("DenominacionFilter", $"%{denominacionFilter}%"); } sqlBuilder.Append(" ORDER BY Denominacion;"); try { using var connection = _connectionFactory.CreateConnection(); return await connection.QueryAsync(sqlBuilder.ToString(), parameters); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener todos los Estados de Bobina. Filtro: {Denominacion}", denominacionFilter); return Enumerable.Empty(); } } public async Task GetByIdAsync(int id) { const string sql = "SELECT Id_EstadoBobina AS IdEstadoBobina, Denominacion, Obs FROM dbo.bob_dtEstadosBobinas WHERE Id_EstadoBobina = @Id"; try { using var connection = _connectionFactory.CreateConnection(); return await connection.QuerySingleOrDefaultAsync(sql, new { Id = id }); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener Estado de Bobina por ID: {IdEstadoBobina}", id); return null; } } public async Task ExistsByDenominacionAsync(string denominacion, int? excludeId = null) { var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.bob_dtEstadosBobinas WHERE Denominacion = @Denominacion"); var parameters = new DynamicParameters(); parameters.Add("Denominacion", denominacion); if (excludeId.HasValue) { sqlBuilder.Append(" AND Id_EstadoBobina != @ExcludeId"); parameters.Add("ExcludeId", excludeId.Value); } try { using var connection = _connectionFactory.CreateConnection(); var count = await connection.ExecuteScalarAsync(sqlBuilder.ToString(), parameters); return count > 0; } catch (Exception ex) { _logger.LogError(ex, "Error en ExistsByDenominacionAsync para Estado de Bobina con denominación: {Denominacion}", denominacion); return true; // Asumir que existe en caso de error } } public async Task IsInUseAsync(int id) { // Verificar si el estado de bobina está referenciado en bob_StockBobinas const string sqlCheckStock = "SELECT TOP 1 1 FROM dbo.bob_StockBobinas WHERE Id_EstadoBobina = @IdEstadoBobina"; try { using var connection = _connectionFactory.CreateConnection(); var inStock = await connection.ExecuteScalarAsync(sqlCheckStock, new { IdEstadoBobina = id }); return inStock.HasValue && inStock.Value == 1; } catch (Exception ex) { _logger.LogError(ex, "Error en IsInUseAsync para Estado de Bobina ID: {IdEstadoBobina}", id); return true; // Asumir en uso si hay error } } // --- Métodos de Escritura (USAN TRANSACCIÓN) --- public async Task CreateAsync(EstadoBobina nuevoEstadoBobina, int idUsuario, IDbTransaction transaction) { const string sqlInsert = @" INSERT INTO dbo.bob_dtEstadosBobinas (Denominacion, Obs) OUTPUT INSERTED.Id_EstadoBobina AS IdEstadoBobina, INSERTED.Denominacion, INSERTED.Obs VALUES (@Denominacion, @Obs);"; const string sqlInsertHistorico = @" INSERT INTO dbo.bob_dtEstadosBobinas_H (Id_EstadoBobina, Denominacion, Obs, Id_Usuario, FechaMod, TipoMod) VALUES (@IdEstadoBobina, @Denominacion, @Obs, @IdUsuario, @FechaMod, @TipoMod);"; var connection = transaction.Connection!; var insertedEstado = await connection.QuerySingleAsync( sqlInsert, new { nuevoEstadoBobina.Denominacion, nuevoEstadoBobina.Obs }, transaction: transaction ); if (insertedEstado == null || insertedEstado.IdEstadoBobina <= 0) { throw new DataException("No se pudo obtener el ID del estado de bobina insertado."); } await connection.ExecuteAsync(sqlInsertHistorico, new { IdEstadoBobina = insertedEstado.IdEstadoBobina, insertedEstado.Denominacion, insertedEstado.Obs, IdUsuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Insertada" }, transaction: transaction); return insertedEstado; } public async Task UpdateAsync(EstadoBobina estadoBobinaAActualizar, int idUsuario, IDbTransaction transaction) { var connection = transaction.Connection!; var estadoActual = await connection.QuerySingleOrDefaultAsync( "SELECT Id_EstadoBobina AS IdEstadoBobina, Denominacion, Obs FROM dbo.bob_dtEstadosBobinas WHERE Id_EstadoBobina = @Id", new { Id = estadoBobinaAActualizar.IdEstadoBobina }, transaction); if (estadoActual == null) throw new KeyNotFoundException($"No se encontró el estado de bobina con ID {estadoBobinaAActualizar.IdEstadoBobina} para actualizar."); const string sqlUpdate = "UPDATE dbo.bob_dtEstadosBobinas SET Denominacion = @Denominacion, Obs = @Obs WHERE Id_EstadoBobina = @IdEstadoBobina;"; const string sqlInsertHistorico = @" INSERT INTO dbo.bob_dtEstadosBobinas_H (Id_EstadoBobina, Denominacion, Obs, Id_Usuario, FechaMod, TipoMod) VALUES (@IdEstadoBobina, @DenominacionActual, @ObsActual, @IdUsuario, @FechaMod, @TipoMod);"; await connection.ExecuteAsync(sqlInsertHistorico, new { IdEstadoBobina = estadoActual.IdEstadoBobina, DenominacionActual = estadoActual.Denominacion, // Valor ANTES ObsActual = estadoActual.Obs, // Valor ANTES IdUsuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Modificada" }, transaction: transaction); var rowsAffected = await connection.ExecuteAsync(sqlUpdate, new { estadoBobinaAActualizar.Denominacion, estadoBobinaAActualizar.Obs, estadoBobinaAActualizar.IdEstadoBobina }, transaction: transaction); return rowsAffected == 1; } public async Task DeleteAsync(int id, int idUsuario, IDbTransaction transaction) { var connection = transaction.Connection!; var estadoActual = await connection.QuerySingleOrDefaultAsync( "SELECT Id_EstadoBobina AS IdEstadoBobina, Denominacion, Obs FROM dbo.bob_dtEstadosBobinas WHERE Id_EstadoBobina = @Id", new { Id = id }, transaction); if (estadoActual == null) throw new KeyNotFoundException($"No se encontró el estado de bobina con ID {id} para eliminar."); const string sqlDelete = "DELETE FROM dbo.bob_dtEstadosBobinas WHERE Id_EstadoBobina = @Id"; const string sqlInsertHistorico = @" INSERT INTO dbo.bob_dtEstadosBobinas_H (Id_EstadoBobina, Denominacion, Obs, Id_Usuario, FechaMod, TipoMod) VALUES (@IdEstadoBobina, @Denominacion, @Obs, @IdUsuario, @FechaMod, @TipoMod);"; await connection.ExecuteAsync(sqlInsertHistorico, new { IdEstadoBobina = estadoActual.IdEstadoBobina, estadoActual.Denominacion, // Valor ANTES estadoActual.Obs, // Valor ANTES IdUsuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Eliminada" }, transaction: transaction); var rowsAffected = await connection.ExecuteAsync(sqlDelete, new { Id = id }, transaction: transaction); return rowsAffected == 1; } public async Task> GetHistorialAsync( DateTime? fechaDesde, DateTime? fechaHasta, int? idUsuarioModifico, string? tipoModificacion, int? idEstadoBobinaOriginal) { using var connection = _connectionFactory.CreateConnection(); var sqlBuilder = new StringBuilder(@" SELECT h.Id_EstadoBobina, h.Denominacion, h.Obs, h.Id_Usuario, h.FechaMod, h.TipoMod, u.Nombre + ' ' + u.Apellido AS NombreUsuarioModifico FROM dbo.bob_dtEstadosBobinas_H h JOIN dbo.gral_Usuarios u ON h.Id_Usuario = u.Id WHERE 1=1"); var parameters = new DynamicParameters(); if (fechaDesde.HasValue) { sqlBuilder.Append(" AND h.FechaMod >= @FechaDesdeParam"); parameters.Add("FechaDesdeParam", fechaDesde.Value.Date); } if (fechaHasta.HasValue) { sqlBuilder.Append(" AND h.FechaMod <= @FechaHastaParam"); parameters.Add("FechaHastaParam", fechaHasta.Value.Date.AddDays(1).AddTicks(-1)); } if (idUsuarioModifico.HasValue) { sqlBuilder.Append(" AND h.Id_Usuario = @IdUsuarioModificoParam"); parameters.Add("IdUsuarioModificoParam", idUsuarioModifico.Value); } if (!string.IsNullOrWhiteSpace(tipoModificacion)) { sqlBuilder.Append(" AND h.TipoMod = @TipoModParam"); parameters.Add("TipoModParam", tipoModificacion); } if (idEstadoBobinaOriginal.HasValue) { sqlBuilder.Append(" AND h.Id_EstadoBobina = @IdEstadoBobinaOriginalParam"); parameters.Add("IdEstadoBobinaOriginalParam", idEstadoBobinaOriginal.Value); } sqlBuilder.Append(" ORDER BY h.FechaMod DESC;"); try { var result = await connection.QueryAsync( sqlBuilder.ToString(), (hist, userName) => (hist, userName), parameters, splitOn: "NombreUsuarioModifico" ); return result; } catch (Exception ex) { _logger.LogError(ex, "Error al obtener historial de Estados de Bobina."); return Enumerable.Empty<(EstadoBobinaHistorico, string)>(); } } } }