using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using SkillManagementDAL.CustomCode.SkillProductMap; using SkillManagementDAL.DTO.SkillGroup; using SkillManagementDAL.DTO.SkillProductMap; using System.Text.Json; namespace SkillManagementBLL.SkillProductMap { public class SkillProductMapBLL : ISkillProductMapBLL { private readonly ISkillProductMapDAL _dal; private readonly AutoNumber _autoNumber; public SkillProductMapBLL(ISkillProductMapDAL dal, AutoNumber autoNumber) { _dal = dal; _autoNumber = autoNumber; } public async Task GetByMapId(int MapId, LoginDTO login, CancellationToken ct) => await _dal.GetByMapId(MapId, login, ct); public async Task GetByProductFamily(int ProductFamilyId, LoginDTO login, CancellationToken ct) => await _dal.GetByProductFamily(ProductFamilyId, login, ct); public async Task GetBySkill(int skillId, LoginDTO login, CancellationToken ct) => await _dal.GetBySkill(skillId, login, ct); public async Task GetSelectList(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct) => await _dal.GetSelectList(criteriaDTO, login, ct); public async Task Save(IEnumerable maps, int skillId, LoginDTO login, CancellationToken ct) { if (skillId == 0) throw new ArgumentException("SkillId is required."); var inputList = maps?.ToList() ?? new List(); if (!inputList.Any()) return "No maps provided."; // Expand each incoming map into one row per (ProductFamilyId, ModelId) combination // — mirrors the SkillIds multi-picklist pattern used in SkillAssessment. var mapList = new List(); foreach (var m in inputList) { var productFamilyIds = (m.ProductFamilyIds != null && m.ProductFamilyIds.Count > 0) ? m.ProductFamilyIds : new List { m.ProductFamilyId }; var modelIds = (m.ModelIds != null && m.ModelIds.Count > 0) ? m.ModelIds : new List { m.ModelId }; bool isExisting = m.MapId > 0; bool first = true; foreach (var productFamilyId in productFamilyIds) { foreach (var modelId in modelIds) { // Only the first combination of an existing row keeps its MapId (update-in-place); // every additional combination becomes a new row. var row = (isExisting && first) ? m : new SkillProductMapDTO { MapId = 0, SkillId = m.SkillId, SlNo = m.SlNo, SpecificParameters = m.SpecificParameters, IsActive = m.IsActive, Remarks = m.Remarks }; row.ProductFamilyId = productFamilyId; row.ModelId = modelId; mapList.Add(row); first = false; } } } // Generate MapIds for new rows var newMaps = mapList.Where(m => m.MapId == 0).ToList(); if (newMaps.Any()) { var an = await _autoNumber.GetNumberAsync(newMaps.Count, "MSKILLPRODUCT", login); int nextId = an.StartNumber; foreach (var m in newMaps) { m.MapId = nextId++; m.SkillId = skillId; } } // Save via DAL await _dal.SaveOrUpdate(mapList, skillId, login, ct); // 🔥 Return MapIds instead of SkillId var mapIds = mapList.Select(m => m.MapId).ToList(); return $"{SuccessResponse.SaveSuccessMessage} MapIds={string.Join(",", mapIds)}"; } public async Task DeleteById(int mapId, LoginDTO login, CancellationToken ct) { var rows = await _dal.DeleteById(mapId, login, ct); if (rows == 0) throw new Exception(ErrorResponse.DeleteNotFoundMessage); return SuccessResponse.DeleteSuccessMessage; } public async Task GetSkillProductMapList(int firstNumber, int maxResult, CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct = default) { // ── VALIDATION ─────────────────────────────────────────── if (firstNumber == -1 && maxResult != -1) throw new ArgumentException("MaxResult must also be -1 when FirstNumber is -1."); if (firstNumber != -1 && maxResult == -1) throw new ArgumentException("FirstNumber must also be -1 when MaxResult is -1."); if (firstNumber != -1 && firstNumber < 1) throw new ArgumentException($"FirstNumber must be >= 1 or -1. Got: {firstNumber}"); if (maxResult != -1 && maxResult < 1) throw new ArgumentException($"MaxResult must be >= 1 or -1. Got: {maxResult}"); // ── FETCH DATA ─────────────────────────────────────────── bool isAllData = firstNumber == -1 && maxResult == -1; List data = isAllData ? await _dal.GetAllList(login, ct) : await _dal.GetPagedList(firstNumber, maxResult, login, ct); // ── SERIALIZE (KEY CHANGE) ──────────────────────────────── var json = JsonSerializer.Serialize(data); return json; } } }