using GestionIntegral.Api.Data; using GestionIntegral.Api.Data.Repositories.Suscripciones; using GestionIntegral.Api.Dtos.Suscripciones; using GestionIntegral.Api.Models.Suscripciones; using System.Data; namespace GestionIntegral.Api.Services.Suscripciones { public class PromocionService : IPromocionService { private readonly IPromocionRepository _promocionRepository; private readonly DbConnectionFactory _connectionFactory; private readonly ILogger _logger; public PromocionService( IPromocionRepository promocionRepository, DbConnectionFactory connectionFactory, ILogger logger) { _promocionRepository = promocionRepository; _connectionFactory = connectionFactory; _logger = logger; } private PromocionDto MapToDto(Promocion promo) { return new PromocionDto { IdPromocion = promo.IdPromocion, Descripcion = promo.Descripcion, TipoEfecto = promo.TipoEfecto, ValorEfecto = promo.ValorEfecto, TipoCondicion = promo.TipoCondicion, ValorCondicion = promo.ValorCondicion, FechaInicio = promo.FechaInicio.ToString("yyyy-MM-dd"), FechaFin = promo.FechaFin?.ToString("yyyy-MM-dd"), Activa = promo.Activa }; } public async Task> ObtenerTodas(bool soloActivas) { var promociones = await _promocionRepository.GetAllAsync(soloActivas); return promociones.Select(MapToDto); } public async Task ObtenerPorId(int id) { var promocion = await _promocionRepository.GetByIdAsync(id); return promocion != null ? MapToDto(promocion) : null; } public async Task<(PromocionDto? Promocion, string? Error)> Crear(CreatePromocionDto createDto, int idUsuario) { if (createDto.FechaFin.HasValue && createDto.FechaFin.Value < createDto.FechaInicio) { return (null, "La fecha de fin no puede ser anterior a la fecha de inicio."); } var nuevaPromocion = new Promocion { Descripcion = createDto.Descripcion, TipoEfecto = createDto.TipoEfecto, ValorEfecto = createDto.ValorEfecto, TipoCondicion = createDto.TipoCondicion, ValorCondicion = createDto.ValorCondicion, FechaInicio = createDto.FechaInicio, FechaFin = createDto.FechaFin, Activa = createDto.Activa, IdUsuarioAlta = idUsuario }; using var connection = _connectionFactory.CreateConnection(); await (connection as System.Data.Common.DbConnection)!.OpenAsync(); using var transaction = connection.BeginTransaction(); try { var promocionCreada = await _promocionRepository.CreateAsync(nuevaPromocion, transaction); if (promocionCreada == null) throw new DataException("Error al crear la promoción."); transaction.Commit(); _logger.LogInformation("Promoción ID {Id} creada por Usuario ID {UserId}.", promocionCreada.IdPromocion, idUsuario); return (MapToDto(promocionCreada), null); } catch (Exception ex) { try { transaction.Rollback(); } catch { } _logger.LogError(ex, "Error al crear promoción: {Descripcion}", createDto.Descripcion); return (null, $"Error interno al crear la promoción: {ex.Message}"); } } public async Task<(bool Exito, string? Error)> Actualizar(int id, UpdatePromocionDto updateDto, int idUsuario) { var existente = await _promocionRepository.GetByIdAsync(id); if (existente == null) return (false, "Promoción no encontrada."); if (updateDto.FechaFin.HasValue && updateDto.FechaFin.Value < updateDto.FechaInicio) { return (false, "La fecha de fin no puede ser anterior a la fecha de inicio."); } existente.Descripcion = updateDto.Descripcion; existente.TipoEfecto = updateDto.TipoEfecto; existente.ValorEfecto = updateDto.ValorEfecto; existente.TipoCondicion = updateDto.TipoCondicion; existente.ValorCondicion = updateDto.ValorCondicion; existente.FechaInicio = updateDto.FechaInicio; existente.FechaFin = updateDto.FechaFin; existente.Activa = updateDto.Activa; using var connection = _connectionFactory.CreateConnection(); await (connection as System.Data.Common.DbConnection)!.OpenAsync(); using var transaction = connection.BeginTransaction(); try { var actualizado = await _promocionRepository.UpdateAsync(existente, transaction); if (!actualizado) throw new DataException("Error al actualizar la promoción."); transaction.Commit(); _logger.LogInformation("Promoción ID {Id} actualizada por Usuario ID {UserId}.", id, idUsuario); return (true, null); } catch (Exception ex) { try { transaction.Rollback(); } catch { } _logger.LogError(ex, "Error al actualizar promoción ID: {Id}", id); return (false, $"Error interno al actualizar: {ex.Message}"); } } } }