using Dapper; using GestionIntegral.Api.Models.Distribucion; 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.Distribucion { public class OtroDestinoRepository : IOtroDestinoRepository { private readonly DbConnectionFactory _connectionFactory; private readonly ILogger _logger; public OtroDestinoRepository(DbConnectionFactory connectionFactory, ILogger logger) { _connectionFactory = connectionFactory; _logger = logger; } public async Task> GetAllAsync(string? nombreFilter) { var sqlBuilder = new StringBuilder("SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE 1=1"); var parameters = new DynamicParameters(); if (!string.IsNullOrWhiteSpace(nombreFilter)) { sqlBuilder.Append(" AND Nombre LIKE @NombreFilter"); parameters.Add("NombreFilter", $"%{nombreFilter}%"); } sqlBuilder.Append(" ORDER BY Nombre;"); try { using var connection = _connectionFactory.CreateConnection(); return await connection.QueryAsync(sqlBuilder.ToString(), parameters); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener todos los Otros Destinos. Filtro: {Nombre}", nombreFilter); return Enumerable.Empty(); } } public async Task GetByIdAsync(int id) { const string sql = "SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id"; try { using var connection = _connectionFactory.CreateConnection(); return await connection.QuerySingleOrDefaultAsync(sql, new { Id = id }); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener Otro Destino por ID: {IdDestino}", id); return null; } } public async Task ExistsByNameAsync(string nombre, int? excludeId = null) { var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.dist_dtOtrosDestinos WHERE Nombre = @Nombre"); var parameters = new DynamicParameters(); parameters.Add("Nombre", nombre); if (excludeId.HasValue) { sqlBuilder.Append(" AND Id_Destino != @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 ExistsByNameAsync para Otro Destino con nombre: {Nombre}", nombre); return true; } } public async Task IsInUseAsync(int id) { const string sqlCheckSalidas = "SELECT TOP 1 1 FROM dbo.dist_SalidasOtrosDestinos WHERE Id_Destino = @IdDestino"; try { using var connection = _connectionFactory.CreateConnection(); var inUse = await connection.ExecuteScalarAsync(sqlCheckSalidas, new { IdDestino = id }); return inUse.HasValue && inUse.Value == 1; } catch (Exception ex) { _logger.LogError(ex, "Error en IsInUseAsync para Otro Destino ID: {IdDestino}", id); return true; } } public async Task CreateAsync(OtroDestino nuevoDestino, int idUsuario, IDbTransaction transaction) { const string sqlInsert = @" INSERT INTO dbo.dist_dtOtrosDestinos (Nombre, Obs) OUTPUT INSERTED.Id_Destino AS IdDestino, INSERTED.Nombre, INSERTED.Obs VALUES (@Nombre, @Obs);"; const string sqlInsertHistorico = @" INSERT INTO dbo.dist_dtOtrosDestinos_H (Id_Destino, Nombre, Obs, Id_Usuario, FechaMod, TipoMod) VALUES (@IdDestino, @Nombre, @Obs, @IdUsuario, @FechaMod, @TipoMod);"; var connection = transaction.Connection!; var insertedDestino = await connection.QuerySingleAsync(sqlInsert, nuevoDestino, transaction); if (insertedDestino == null || insertedDestino.IdDestino <= 0) { throw new DataException("No se pudo obtener el ID del otro destino insertado."); } await connection.ExecuteAsync(sqlInsertHistorico, new { IdDestino = insertedDestino.IdDestino, insertedDestino.Nombre, insertedDestino.Obs, IdUsuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Insertada" }, transaction); return insertedDestino; } public async Task UpdateAsync(OtroDestino destinoAActualizar, int idUsuario, IDbTransaction transaction) { var connection = transaction.Connection!; var destinoActual = await connection.QuerySingleOrDefaultAsync( "SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id", new { Id = destinoAActualizar.IdDestino }, transaction); if (destinoActual == null) throw new KeyNotFoundException($"Otro Destino con ID {destinoAActualizar.IdDestino} no encontrado."); const string sqlUpdate = "UPDATE dbo.dist_dtOtrosDestinos SET Nombre = @Nombre, Obs = @Obs WHERE Id_Destino = @IdDestino;"; const string sqlInsertHistorico = @" INSERT INTO dbo.dist_dtOtrosDestinos_H (Id_Destino, Nombre, Obs, Id_Usuario, FechaMod, TipoMod) VALUES (@IdDestino, @NombreActual, @ObsActual, @IdUsuario, @FechaMod, @TipoMod);"; await connection.ExecuteAsync(sqlInsertHistorico, new { IdDestino = destinoActual.IdDestino, NombreActual = destinoActual.Nombre, ObsActual = destinoActual.Obs, IdUsuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Modificada" }, transaction); var rowsAffected = await connection.ExecuteAsync(sqlUpdate, destinoAActualizar, transaction); return rowsAffected == 1; } public async Task DeleteAsync(int id, int idUsuario, IDbTransaction transaction) { var connection = transaction.Connection!; var destinoActual = await connection.QuerySingleOrDefaultAsync( "SELECT Id_Destino AS IdDestino, Nombre, Obs FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id", new { Id = id }, transaction); if (destinoActual == null) throw new KeyNotFoundException($"Otro Destino con ID {id} no encontrado."); const string sqlDelete = "DELETE FROM dbo.dist_dtOtrosDestinos WHERE Id_Destino = @Id"; const string sqlInsertHistorico = @" INSERT INTO dbo.dist_dtOtrosDestinos_H (Id_Destino, Nombre, Obs, Id_Usuario, FechaMod, TipoMod) VALUES (@IdDestino, @Nombre, @Obs, @IdUsuario, @FechaMod, @TipoMod);"; await connection.ExecuteAsync(sqlInsertHistorico, new { IdDestino = destinoActual.IdDestino, destinoActual.Nombre, destinoActual.Obs, IdUsuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Eliminada" }, transaction); var rowsAffected = await connection.ExecuteAsync(sqlDelete, new { Id = id }, transaction); return rowsAffected == 1; } } }