using GestionIntegral.Api.Data; using GestionIntegral.Api.Data.Repositories.Suscripciones; using GestionIntegral.Api.Data.Repositories.Usuarios; using GestionIntegral.Api.Dtos.Suscripciones; using GestionIntegral.Api.Models.Suscripciones; using System.Data; namespace GestionIntegral.Api.Services.Suscripciones { public class AjusteService : IAjusteService { private readonly IAjusteRepository _ajusteRepository; private readonly ISuscriptorRepository _suscriptorRepository; private readonly IUsuarioRepository _usuarioRepository; private readonly DbConnectionFactory _connectionFactory; private readonly ILogger _logger; public AjusteService( IAjusteRepository ajusteRepository, ISuscriptorRepository suscriptorRepository, IUsuarioRepository usuarioRepository, DbConnectionFactory connectionFactory, ILogger logger) { _ajusteRepository = ajusteRepository; _suscriptorRepository = suscriptorRepository; _usuarioRepository = usuarioRepository; _connectionFactory = connectionFactory; _logger = logger; } private async Task MapToDto(Ajuste ajuste) { if (ajuste == null) return null; var usuario = await _usuarioRepository.GetByIdAsync(ajuste.IdUsuarioAlta); return new AjusteDto { IdAjuste = ajuste.IdAjuste, IdSuscriptor = ajuste.IdSuscriptor, TipoAjuste = ajuste.TipoAjuste, Monto = ajuste.Monto, Motivo = ajuste.Motivo, Estado = ajuste.Estado, IdFacturaAplicado = ajuste.IdFacturaAplicado, FechaAlta = ajuste.FechaAlta.ToString("yyyy-MM-dd HH:mm"), NombreUsuarioAlta = usuario != null ? $"{usuario.Nombre} {usuario.Apellido}" : "N/A" }; } public async Task> ObtenerAjustesPorSuscriptor(int idSuscriptor) { var ajustes = await _ajusteRepository.GetAjustesPorSuscriptorAsync(idSuscriptor); var dtosTasks = ajustes.Select(a => MapToDto(a)); var dtos = await Task.WhenAll(dtosTasks); return dtos.Where(dto => dto != null)!; } public async Task<(AjusteDto? Ajuste, string? Error)> CrearAjusteManual(CreateAjusteDto createDto, int idUsuario) { var suscriptor = await _suscriptorRepository.GetByIdAsync(createDto.IdSuscriptor); if (suscriptor == null) { return (null, "El suscriptor especificado no existe."); } var nuevoAjuste = new Ajuste { IdSuscriptor = createDto.IdSuscriptor, TipoAjuste = createDto.TipoAjuste, Monto = createDto.Monto, Motivo = createDto.Motivo, IdUsuarioAlta = idUsuario }; using var connection = _connectionFactory.CreateConnection(); await (connection as System.Data.Common.DbConnection)!.OpenAsync(); using var transaction = connection.BeginTransaction(); try { var ajusteCreado = await _ajusteRepository.CreateAsync(nuevoAjuste, transaction); if (ajusteCreado == null) throw new DataException("Error al crear el registro de ajuste."); transaction.Commit(); _logger.LogInformation("Ajuste manual ID {IdAjuste} creado para Suscriptor ID {IdSuscriptor} por Usuario ID {IdUsuario}", ajusteCreado.IdAjuste, ajusteCreado.IdSuscriptor, idUsuario); var dto = await MapToDto(ajusteCreado); return (dto, null); } catch (Exception ex) { try { transaction.Rollback(); } catch { } _logger.LogError(ex, "Error al crear ajuste manual para Suscriptor ID {IdSuscriptor}", createDto.IdSuscriptor); return (null, "Error interno al registrar el ajuste."); } } public async Task<(bool Exito, string? Error)> AnularAjuste(int idAjuste, int idUsuario) { using var connection = _connectionFactory.CreateConnection(); await (connection as System.Data.Common.DbConnection)!.OpenAsync(); using var transaction = connection.BeginTransaction(); try { var ajuste = await _ajusteRepository.GetByIdAsync(idAjuste); if (ajuste == null) return (false, "Ajuste no encontrado."); if (ajuste.Estado != "Pendiente") return (false, $"No se puede anular un ajuste en estado '{ajuste.Estado}'."); var exito = await _ajusteRepository.AnularAjusteAsync(idAjuste, idUsuario, transaction); if (!exito) throw new DataException("No se pudo anular el ajuste."); transaction.Commit(); _logger.LogInformation("Ajuste ID {IdAjuste} anulado por Usuario ID {IdUsuario}", idAjuste, idUsuario); return (true, null); } catch (Exception ex) { try { transaction.Rollback(); } catch { } _logger.LogError(ex, "Error al anular ajuste ID {IdAjuste}", idAjuste); return (false, "Error interno al anular el ajuste."); } } } }