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 PublicacionRepository : IPublicacionRepository { private readonly DbConnectionFactory _connectionFactory; private readonly ILogger _logger; public PublicacionRepository(DbConnectionFactory connectionFactory, ILogger logger) { _connectionFactory = connectionFactory; _logger = logger; } public async Task> GetAllAsync(string? nombreFilter, int? idEmpresaFilter, bool? soloHabilitadas) { var sqlBuilder = new StringBuilder(@" SELECT p.*, e.Nombre AS NombreEmpresa FROM dbo.dist_dtPublicaciones p INNER JOIN dbo.dist_dtEmpresas e ON p.Id_Empresa = e.Id_Empresa WHERE 1=1"); var parameters = new DynamicParameters(); if (soloHabilitadas.HasValue) { sqlBuilder.Append(soloHabilitadas.Value ? " AND p.Habilitada = 1" : " AND (p.Habilitada = 0 OR p.Habilitada IS NULL)"); } if (!string.IsNullOrWhiteSpace(nombreFilter)) { sqlBuilder.Append(" AND p.Nombre LIKE @Nombre"); parameters.Add("Nombre", $"%{nombreFilter}%"); } if (idEmpresaFilter.HasValue && idEmpresaFilter > 0) { sqlBuilder.Append(" AND p.Id_Empresa = @IdEmpresa"); parameters.Add("IdEmpresa", idEmpresaFilter.Value); } sqlBuilder.Append(" ORDER BY p.Nombre;"); try { using var connection = _connectionFactory.CreateConnection(); return await connection.QueryAsync( sqlBuilder.ToString(), (pub, empNombre) => (pub, empNombre), parameters, splitOn: "NombreEmpresa" ); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener todas las Publicaciones."); return Enumerable.Empty<(Publicacion, string)>(); } } public async Task<(Publicacion? Publicacion, string? NombreEmpresa)> GetByIdAsync(int id) { const string sql = @" SELECT p.*, e.Nombre AS NombreEmpresa FROM dbo.dist_dtPublicaciones p INNER JOIN dbo.dist_dtEmpresas e ON p.Id_Empresa = e.Id_Empresa WHERE p.Id_Publicacion = @Id"; try { using var connection = _connectionFactory.CreateConnection(); var result = await connection.QueryAsync( sql, (pub, empNombre) => (pub, empNombre), new { Id = id }, splitOn: "NombreEmpresa" ); return result.SingleOrDefault(); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener Publicación por ID: {IdPublicacion}", id); return (null, null); } } public async Task GetByIdSimpleAsync(int id) { const string sql = "SELECT * FROM dbo.dist_dtPublicaciones WHERE Id_Publicacion = @Id"; using var connection = _connectionFactory.CreateConnection(); return await connection.QuerySingleOrDefaultAsync(sql, new { Id = id }); } public async Task ExistsByNameAndEmpresaAsync(string nombre, int idEmpresa, int? excludeIdPublicacion = null) { var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.dist_dtPublicaciones WHERE Nombre = @Nombre AND Id_Empresa = @IdEmpresa"); var parameters = new DynamicParameters(); parameters.Add("Nombre", nombre); parameters.Add("IdEmpresa", idEmpresa); if (excludeIdPublicacion.HasValue) { sqlBuilder.Append(" AND Id_Publicacion != @ExcludeId"); parameters.Add("ExcludeId", excludeIdPublicacion.Value); } using var connection = _connectionFactory.CreateConnection(); return await connection.ExecuteScalarAsync(sqlBuilder.ToString(), parameters); } public async Task IsInUseAsync(int id) { // Verificar en tablas relacionadas: dist_EntradasSalidas, dist_EntradasSalidasCanillas, // dist_Precios, dist_RecargoZona, dist_PorcPago, dist_PorcMonPagoCanilla, dist_dtPubliSecciones, // bob_RegPublicaciones, bob_StockBobinas (donde Id_Publicacion se usa) using var connection = _connectionFactory.CreateConnection(); string[] checkQueries = { "SELECT TOP 1 1 FROM dbo.dist_EntradasSalidas WHERE Id_Publicacion = @Id", "SELECT TOP 1 1 FROM dbo.dist_EntradasSalidasCanillas WHERE Id_Publicacion = @Id", "SELECT TOP 1 1 FROM dbo.dist_Precios WHERE Id_Publicacion = @Id", "SELECT TOP 1 1 FROM dbo.dist_RecargoZona WHERE Id_Publicacion = @Id", "SELECT TOP 1 1 FROM dbo.dist_PorcPago WHERE Id_Publicacion = @Id", "SELECT TOP 1 1 FROM dbo.dist_PorcMonPagoCanilla WHERE Id_Publicacion = @Id", "SELECT TOP 1 1 FROM dbo.dist_dtPubliSecciones WHERE Id_Publicacion = @Id", "SELECT TOP 1 1 FROM dbo.bob_RegPublicaciones WHERE Id_Publicacion = @Id", "SELECT TOP 1 1 FROM dbo.bob_StockBobinas WHERE Id_Publicacion = @Id" }; foreach (var query in checkQueries) { if (await connection.ExecuteScalarAsync(query, new { Id = id }) == 1) return true; } return false; } public async Task CreateAsync(Publicacion nuevaPublicacion, int idUsuario, IDbTransaction transaction) { // Habilitada por defecto es true si es null en el modelo nuevaPublicacion.Habilitada ??= true; const string sqlInsert = @" INSERT INTO dbo.dist_dtPublicaciones (Nombre, Observacion, Id_Empresa, CtrlDevoluciones, Habilitada) OUTPUT INSERTED.* VALUES (@Nombre, @Observacion, @IdEmpresa, @CtrlDevoluciones, @Habilitada);"; const string sqlInsertHistorico = @" INSERT INTO dbo.dist_dtPublicaciones_H (Id_Publicacion, Nombre, Observacion, Id_Empresa, Habilitada, Id_Usuario, FechaMod, TipoMod) VALUES (@IdPublicacion, @Nombre, @Observacion, @IdEmpresa, @Habilitada, @Id_Usuario, @FechaMod, @TipoMod);"; var connection = transaction.Connection!; var inserted = await connection.QuerySingleAsync(sqlInsert, nuevaPublicacion, transaction); if (inserted == null) throw new DataException("Error al crear la publicación."); await connection.ExecuteAsync(sqlInsertHistorico, new { inserted.IdPublicacion, inserted.Nombre, inserted.Observacion, inserted.IdEmpresa, Habilitada = inserted.Habilitada ?? true, // Asegurar que no sea null para el historial Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Creada" }, transaction); return inserted; } public async Task UpdateAsync(Publicacion publicacionAActualizar, int idUsuario, IDbTransaction transaction) { var connection = transaction.Connection!; var actual = await connection.QuerySingleOrDefaultAsync( "SELECT * FROM dbo.dist_dtPublicaciones WHERE Id_Publicacion = @IdPublicacion", new { publicacionAActualizar.IdPublicacion }, transaction); if (actual == null) throw new KeyNotFoundException("Publicación no encontrada."); publicacionAActualizar.Habilitada ??= true; // Asegurar que no sea null const string sqlUpdate = @" UPDATE dbo.dist_dtPublicaciones SET Nombre = @Nombre, Observacion = @Observacion, Id_Empresa = @IdEmpresa, CtrlDevoluciones = @CtrlDevoluciones, Habilitada = @Habilitada WHERE Id_Publicacion = @IdPublicacion;"; const string sqlInsertHistorico = @" INSERT INTO dbo.dist_dtPublicaciones_H (Id_Publicacion, Nombre, Observacion, Id_Empresa, Habilitada, Id_Usuario, FechaMod, TipoMod) VALUES (@IdPublicacion, @Nombre, @Observacion, @IdEmpresa, @Habilitada, @Id_Usuario, @FechaMod, @TipoMod);"; await connection.ExecuteAsync(sqlInsertHistorico, new { IdPublicacion = actual.IdPublicacion, Nombre = actual.Nombre, Observacion = actual.Observacion, IdEmpresa = actual.IdEmpresa, Habilitada = actual.Habilitada ?? true, Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Actualizada" }, transaction); var rowsAffected = await connection.ExecuteAsync(sqlUpdate, publicacionAActualizar, transaction); return rowsAffected == 1; } public async Task DeleteAsync(int id, int idUsuario, IDbTransaction transaction) { var connection = transaction.Connection!; var actual = await connection.QuerySingleOrDefaultAsync( "SELECT * FROM dbo.dist_dtPublicaciones WHERE Id_Publicacion = @Id", new { Id = id }, transaction); if (actual == null) throw new KeyNotFoundException("Publicación no encontrada."); const string sqlDelete = "DELETE FROM dbo.dist_dtPublicaciones WHERE Id_Publicacion = @Id"; const string sqlInsertHistorico = @" INSERT INTO dbo.dist_dtPublicaciones_H (Id_Publicacion, Nombre, Observacion, Id_Empresa, Habilitada, Id_Usuario, FechaMod, TipoMod) VALUES (@IdPublicacion, @Nombre, @Observacion, @IdEmpresa, @Habilitada, @Id_Usuario, @FechaMod, @TipoMod);"; await connection.ExecuteAsync(sqlInsertHistorico, new { IdPublicacion = actual.IdPublicacion, actual.Nombre, actual.Observacion, actual.IdEmpresa, Habilitada = actual.Habilitada ?? true, Id_Usuario = idUsuario, FechaMod = DateTime.Now, TipoMod = "Eliminada" }, transaction); var rowsAffected = await connection.ExecuteAsync(sqlDelete, new { Id = id }, transaction); return rowsAffected == 1; } } }