using Domain.Dtos.Stock; using Domain.Entities; using Domain.Generics; using Microsoft.EntityFrameworkCore; using Models.Helpers; using Models.Interfaces; using Models.Models; namespace Models.Repositories { public class PhLSMProductRepository(PhronCareOperationsHubContext context) : IPhLSMProductRepository { private readonly PhronCareOperationsHubContext _context = context; public async Task> SearchAsync(LSProductSearchParams searchParams) { var query = _context.PhLsmProducts .Include(p => p.Division) .Include(p => p.Unit) .AsQueryable(); if (!string.IsNullOrWhiteSpace(searchParams.Code)) { var lowered = searchParams.Code.ToLower(); query = query.Where(p => (!string.IsNullOrEmpty(p.FactoryCode) && p.FactoryCode.ToLower().Contains(lowered)) || (!string.IsNullOrEmpty(p.ExternalCode) && p.ExternalCode.ToLower().Contains(lowered))); } if (!string.IsNullOrWhiteSpace(searchParams.Description)) { var lowered = searchParams.Description.ToLower(); query = query.Where(p => (!string.IsNullOrEmpty(p.Name) && p.Name.ToLower().Contains(lowered)) || (!string.IsNullOrEmpty(p.Descripcion) && p.Descripcion.ToLower().Contains(lowered))); } if (searchParams.ProductType.HasValue) query = query.Where(p => p.ProductType == searchParams.ProductType); if (searchParams.TraceabilityType.HasValue) query = query.Where(p => p.TraceabilityType == searchParams.TraceabilityType); if (searchParams.DivisionId.HasValue) query = query.Where(p => p.DivisionId == searchParams.DivisionId); if (searchParams.UnitId.HasValue) query = query.Where(p => p.UnitId == searchParams.UnitId); if (searchParams.PlusProcess.HasValue) query = query.Where(p => p.PlusProcess == searchParams.PlusProcess); var paged = await query.ToPagedResultAsync(searchParams.Page, searchParams.PageSize); return new PagedResult { Items = paged.Items.Select(EntityMapper.MapEntity), TotalItems = paged.TotalItems, Page = paged.Page, PageSize = paged.PageSize }; } public async Task GetByIdAsync(int id) { var entity = await _context.PhLsmProducts .Include(p => p.Division) .Include(p => p.Unit) .FirstOrDefaultAsync(p => p.Id == id); return entity != null ? EntityMapper.MapEntity(entity) : null; } public async Task CreateAsync(ELSProduct entity) { var mapped = EntityMapper.MapEntity(entity); _context.PhLsmProducts.Add(mapped); await _context.SaveChangesAsync(); return EntityMapper.MapEntity(mapped); } public async Task UpdateAsync(ELSProduct entity) { var existing = await _context.PhLsmProducts.FindAsync(entity.Id); if (existing == null) return false; EntityMapper.MapEntityToExisting(entity, existing); await _context.SaveChangesAsync(); return true; } public async Task DeleteAsync(int id) { var entity = await _context.PhLsmProducts.FindAsync(id); if (entity == null) return false; _context.PhLsmProducts.Remove(entity); await _context.SaveChangesAsync(); return true; } public async Task ImportProductsAsync(List items) { // 1. Prevenir nulos/vacíos if (items == null || items.Count == 0) return new ProductImportResultDto { Inserted = 0, Skipped = 0 }; // 2. Obtener todos los códigos únicos de División y Unidad var divisionCodes = items.Select(x => x.DivisionCode).Distinct().ToList(); var unitCodes = items.Select(x => x.UnitCode).Distinct().ToList(); // 3. Mapear a IDs desde la base var divisionMap = await _context.PhLsmProductDivisions .Where(d => divisionCodes.Contains(d.Code)) .ToDictionaryAsync(d => d.Code, d => d.Id); var unitMap = await _context.PhLsmUnitOfMeasures .Where(u => unitCodes.Contains(u.Code)) .ToDictionaryAsync(u => u.Code, u => u.Id); // 4. Armar entidades para insertar (sólo si las FK existen) var toInsert = new List(); int skipped = 0; foreach (var item in items) { // Validaciones de existencia de Division y Unidad if (!divisionMap.TryGetValue(item.DivisionCode, out var divisionId) || !unitMap.TryGetValue(item.UnitCode, out var unitId)) { skipped++; continue; // Saltea el producto si alguna FK no existe } // Armá la entidad var entity = new PhLsmProduct { FactoryCode = item.FactoryCode, Name = item.Name, Descripcion = item.Description, ProductType = item.ProductType, TraceabilityType = item.TraceabilityType, DivisionId = divisionId, UnitId = unitId, PlusProcess = item.PlusProcess, ExternalCode = item.ExternalCode, RegulatoryCode = item.RegulatoryCode // otros campos... }; toInsert.Add(entity); } // 5. Insertar en batch if (toInsert.Count > 0) { _context.PhLsmProducts.AddRange(toInsert); await _context.SaveChangesAsync(); } // 6. Retornar resumen return new ProductImportResultDto { Inserted = toInsert.Count, Skipped = skipped }; } } }