using Dapper; using GestionIntegral.Api.Models.Suscripciones; using System.Data; using System.Text; namespace GestionIntegral.Api.Data.Repositories.Suscripciones { public class SuscriptorRepository : ISuscriptorRepository { private readonly DbConnectionFactory _connectionFactory; private readonly ILogger _logger; public SuscriptorRepository(DbConnectionFactory connectionFactory, ILogger logger) { _connectionFactory = connectionFactory; _logger = logger; } public async Task> GetAllAsync(string? nombreFilter, string? nroDocFilter, bool soloActivos) { var sqlBuilder = new StringBuilder(@" SELECT IdSuscriptor, NombreCompleto, Email, Telefono, Direccion, TipoDocumento, NroDocumento, CBU, IdFormaPagoPreferida, Observaciones, Activo, IdUsuarioAlta, FechaAlta, IdUsuarioMod, FechaMod FROM dbo.susc_Suscriptores WHERE 1=1"); var parameters = new DynamicParameters(); if (soloActivos) { sqlBuilder.Append(" AND Activo = 1"); } if (!string.IsNullOrWhiteSpace(nombreFilter)) { sqlBuilder.Append(" AND NombreCompleto LIKE @NombreFilter"); parameters.Add("NombreFilter", $"%{nombreFilter}%"); } if (!string.IsNullOrWhiteSpace(nroDocFilter)) { sqlBuilder.Append(" AND NroDocumento LIKE @NroDocFilter"); parameters.Add("NroDocFilter", $"%{nroDocFilter}%"); } sqlBuilder.Append(" ORDER BY NombreCompleto;"); try { using var connection = _connectionFactory.CreateConnection(); return await connection.QueryAsync(sqlBuilder.ToString(), parameters); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener todos los Suscriptores."); return Enumerable.Empty(); } } public async Task GetByIdAsync(int id) { const string sql = @" SELECT IdSuscriptor, NombreCompleto, Email, Telefono, Direccion, TipoDocumento, NroDocumento, CBU, IdFormaPagoPreferida, Observaciones, Activo, IdUsuarioAlta, FechaAlta, IdUsuarioMod, FechaMod FROM dbo.susc_Suscriptores WHERE IdSuscriptor = @Id;"; try { using var connection = _connectionFactory.CreateConnection(); return await connection.QuerySingleOrDefaultAsync(sql, new { Id = id }); } catch (Exception ex) { _logger.LogError(ex, "Error al obtener Suscriptor por ID: {IdSuscriptor}", id); return null; } } public async Task ExistsByDocumentoAsync(string tipoDocumento, string nroDocumento, int? excludeId = null) { var sqlBuilder = new StringBuilder("SELECT COUNT(1) FROM dbo.susc_Suscriptores WHERE TipoDocumento = @TipoDocumento AND NroDocumento = @NroDocumento"); var parameters = new DynamicParameters(); parameters.Add("TipoDocumento", tipoDocumento); parameters.Add("NroDocumento", nroDocumento); if (excludeId.HasValue) { sqlBuilder.Append(" AND IdSuscriptor != @ExcludeId"); parameters.Add("ExcludeId", excludeId.Value); } try { using var connection = _connectionFactory.CreateConnection(); return await connection.ExecuteScalarAsync(sqlBuilder.ToString(), parameters); } catch (Exception ex) { _logger.LogError(ex, "Error en ExistsByDocumentoAsync para Suscriptor."); return true; // Asumir que existe si hay error para prevenir duplicados. } } public async Task IsInUseAsync(int id) { // Un suscriptor está en uso si tiene suscripciones activas. const string sql = "SELECT TOP 1 1 FROM dbo.susc_Suscripciones WHERE IdSuscriptor = @Id AND Estado = 'Activa'"; try { using var connection = _connectionFactory.CreateConnection(); var inUse = await connection.ExecuteScalarAsync(sql, new { Id = id }); return inUse.HasValue && inUse.Value == 1; } catch (Exception ex) { _logger.LogError(ex, "Error en IsInUseAsync para Suscriptor ID: {IdSuscriptor}", id); return true; // Asumir en uso si hay error. } } public async Task CreateAsync(Suscriptor nuevoSuscriptor, IDbTransaction transaction) { if (transaction == null || transaction.Connection == null) { throw new ArgumentNullException(nameof(transaction), "La transacción o su conexión no pueden ser nulas."); } const string sqlInsert = @" INSERT INTO dbo.susc_Suscriptores (NombreCompleto, Email, Telefono, Direccion, TipoDocumento, NroDocumento, CBU, IdFormaPagoPreferida, Observaciones, Activo, IdUsuarioAlta, FechaAlta) OUTPUT INSERTED.* VALUES (@NombreCompleto, @Email, @Telefono, @Direccion, @TipoDocumento, @NroDocumento, @CBU, @IdFormaPagoPreferida, @Observaciones, 1, @IdUsuarioAlta, GETDATE());"; var suscriptorCreado = await transaction.Connection.QuerySingleAsync( sqlInsert, nuevoSuscriptor, transaction: transaction ); // No se necesita historial para la creación, ya que la propia tabla tiene campos de auditoría. // Si se necesitara una tabla _H, aquí iría el INSERT a esa tabla. return suscriptorCreado; } public async Task UpdateAsync(Suscriptor suscriptor, IDbTransaction transaction) { // El servicio ya ha poblado IdUsuarioMod y FechaMod en la entidad. const string sqlUpdate = @" UPDATE dbo.susc_Suscriptores SET NombreCompleto = @NombreCompleto, Email = @Email, Telefono = @Telefono, Direccion = @Direccion, TipoDocumento = @TipoDocumento, NroDocumento = @NroDocumento, CBU = @CBU, IdFormaPagoPreferida = @IdFormaPagoPreferida, Observaciones = @Observaciones, IdUsuarioMod = @IdUsuarioMod, FechaMod = @FechaMod WHERE IdSuscriptor = @IdSuscriptor;"; if (transaction == null || transaction.Connection == null) { throw new ArgumentNullException(nameof(transaction), "La transacción o su conexión no pueden ser nulas."); } var rowsAffected = await transaction.Connection.ExecuteAsync(sqlUpdate, suscriptor, transaction: transaction); return rowsAffected == 1; } public async Task ToggleActivoAsync(int id, bool activar, int idUsuario, IDbTransaction transaction) { const string sqlToggle = @" UPDATE dbo.susc_Suscriptores SET Activo = @Activar, IdUsuarioMod = @IdUsuario, FechaMod = GETDATE() WHERE IdSuscriptor = @Id;"; if (transaction == null || transaction.Connection == null) { throw new ArgumentNullException(nameof(transaction), "La transacción o su conexión no pueden ser nulas."); } var rowsAffected = await transaction.Connection.ExecuteAsync( sqlToggle, new { Activar = activar, IdUsuario = idUsuario, Id = id }, transaction: transaction ); return rowsAffected == 1; } } }