using GestionIntegral.Api.Data.Repositories; // Para IZonaRepository using GestionIntegral.Api.Data.Repositories.Distribucion; using GestionIntegral.Api.Dtos.Auditoria; using GestionIntegral.Api.Dtos.Zonas; using GestionIntegral.Api.Models.Distribucion; // Para Zona using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace GestionIntegral.Api.Services.Distribucion { public class ZonaService : IZonaService { private readonly IZonaRepository _zonaRepository; private readonly ILogger _logger; public ZonaService(IZonaRepository zonaRepository, ILogger logger) { _zonaRepository = zonaRepository; _logger = logger; } public async Task> ObtenerTodasAsync(string? nombreFilter, string? descripcionFilter) { var zonas = await _zonaRepository.GetAllAsync(nombreFilter, descripcionFilter, soloActivas: true); // Solo activas por defecto // Mapeo Entidad -> DTO return zonas.Select(z => new ZonaDto { IdZona = z.IdZona, Nombre = z.Nombre, Descripcion = z.Descripcion }); } public async Task ObtenerPorIdAsync(int id) { var zona = await _zonaRepository.GetByIdAsync(id, soloActivas: true); // Solo activa por defecto if (zona == null) return null; // Mapeo Entidad -> DTO return new ZonaDto { IdZona = zona.IdZona, Nombre = zona.Nombre, Descripcion = zona.Descripcion }; } public async Task<(ZonaDto? Zona, string? Error)> CrearAsync(CreateZonaDto createDto, int idUsuario) { // Validación: Nombre duplicado (entre zonas activas) if (await _zonaRepository.ExistsByNameAsync(createDto.Nombre, null, soloActivas: true)) { return (null, "El nombre de la zona ya existe."); } var nuevaZona = new Zona { Nombre = createDto.Nombre, Descripcion = createDto.Descripcion, Estado = true // Las zonas nuevas siempre están activas }; var zonaCreada = await _zonaRepository.CreateAsync(nuevaZona, idUsuario); if (zonaCreada == null) { _logger.LogError("Falló la creación de la Zona en el repositorio para el nombre: {Nombre}", createDto.Nombre); return (null, "Error al crear la zona en la base de datos."); } // Mapeo de Entidad creada a DTO var zonaDto = new ZonaDto { IdZona = zonaCreada.IdZona, Nombre = zonaCreada.Nombre, Descripcion = zonaCreada.Descripcion }; return (zonaDto, null); // Éxito } public async Task<(bool Exito, string? Error)> ActualizarAsync(int id, UpdateZonaDto updateDto, int idUsuario) { // Verificar si la zona existe y está activa para poder modificarla (regla de negocio) var zonaExistente = await _zonaRepository.GetByIdAsync(id, soloActivas: true); if (zonaExistente == null) { // Podría no existir o estar inactiva var zonaInactiva = await _zonaRepository.GetByIdAsync(id, soloActivas: false); if (zonaInactiva != null) return (false, "No se puede modificar una zona eliminada (inactiva)."); else return (false, "Zona no encontrada."); } // Validación: Nombre duplicado (excluyendo el ID actual, entre zonas activas) if (await _zonaRepository.ExistsByNameAsync(updateDto.Nombre, id, soloActivas: true)) { return (false, "El nombre de la zona ya existe para otro registro activo."); } // Mapeo de DTO a Entidad para actualizar zonaExistente.Nombre = updateDto.Nombre; zonaExistente.Descripcion = updateDto.Descripcion; // No modificamos el estado aquí, solo nombre y descripción var actualizado = await _zonaRepository.UpdateAsync(zonaExistente, idUsuario); if (!actualizado) { _logger.LogError("Falló la actualización de la Zona en el repositorio para el ID: {Id}", id); return (false, "Error al actualizar la zona en la base de datos."); } return (true, null); // Éxito } public async Task<(bool Exito, string? Error)> EliminarAsync(int id, int idUsuario) { // Verificar si la zona existe (incluso si está inactiva, para evitar errores) var zonaExistente = await _zonaRepository.GetByIdAsync(id, soloActivas: false); if (zonaExistente == null) { return (false, "Zona no encontrada."); } // Si ya está inactiva, consideramos la operación exitosa (idempotencia) if (!zonaExistente.Estado) { return (true, null); } // Validación: No se puede eliminar si está en uso por distribuidores o canillas activos if (await _zonaRepository.IsInUseAsync(id)) { return (false, "No se puede eliminar. La zona está asignada a distribuidores o canillas activos."); } // Realizar el Soft Delete var eliminado = await _zonaRepository.SoftDeleteAsync(id, idUsuario); if (!eliminado) { _logger.LogError("Falló la eliminación lógica de la Zona en el repositorio para el ID: {Id}", id); return (false, "Error al eliminar la zona de la base de datos."); } return (true, null); // Éxito } public async Task> ObtenerHistorialAsync( DateTime? fechaDesde, DateTime? fechaHasta, int? idUsuarioModifico, string? tipoModificacion, int? idZonaAfectada) { var historialData = await _zonaRepository.GetHistorialAsync(fechaDesde, fechaHasta, idUsuarioModifico, tipoModificacion, idZonaAfectada); return historialData.Select(h => new ZonaHistorialDto { Id_Zona = h.Historial.Id_Zona, Nombre = h.Historial.Nombre, Descripcion = h.Historial.Descripcion, Estado = h.Historial.Estado, Id_Usuario = h.Historial.Id_Usuario, NombreUsuarioModifico = h.NombreUsuarioModifico, FechaMod = h.Historial.FechaMod, TipoMod = h.Historial.TipoMod }).ToList(); } } }