using AmpDAL.CustomCode.API; using AmpDAL.DTO.API; using GB5Shared.DaprCache; using GB5Shared.DTO.Framework.AutoNumber; using GB5Shared.DTO.Framework.Criteria; using GB5Shared.DTO.Framework.Login; using GB5Shared.EventLogPublish; using GB5Shared.GB5Constant; using GB5Shared.GenerateAutoNumber; using GB5Shared.Resource.Response; using GB5Shared.Validation; using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace AMPBLL.API; public class APIBLL( IAPIDAL _dal, IValidation _validation, KeyInvalidate _keyInvalidate, AutoNumber _autoNumber, EventLogPublish _eventLog, ILogger _logger ) : IAPIBLL { // ===================================================== // GET SINGLE // ===================================================== public async Task GetAPIAsync(long APIId, int tenantId, LoginDTO login, CancellationToken ct) { try { return await _dal.GetAPIAsync(APIId, tenantId, login, ct); } catch (Exception ex) { _logger.LogError(ex, "GetAPI failed for APIId {APIId}", APIId); throw; } } // ===================================================== // SELECT LIST // FIX: return string OR update DAL to typed list // ===================================================== public async Task> GetAPISelectListAsync(CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct) { try { return await _dal.GetAPISelectListAsync(criteriaDTO, login, ct); } catch (Exception ex) { _logger.LogError(ex, "GetAPISelectList failed TenantId {TenantId}", login.ClientId); throw; } } // ===================================================== // LIST (PAGED / ALL) // ===================================================== public async Task> GetAPIList( int firstNumber, int maxResult, CriteriaDTO criteriaDTO, LoginDTO login, CancellationToken ct = default) { 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}"); return (firstNumber == -1 && maxResult == -1) ? await _dal.GetAllList(login, ct) : await _dal.GetPagedList(firstNumber, maxResult, login, ct); } // ===================================================== // DELETE // ===================================================== public async Task DeleteById(int mapId, LoginDTO login, CancellationToken ct) { await _dal.DeleteById(mapId, login, ct); return SuccessResponse.DeleteSuccessMessage; } // ===================================================== // SAVE / UPDATE // ===================================================== public async Task SaveAPIAsync(APISaveDTO dto, LoginDTO login, CancellationToken ct) { if (dto == null) throw new ArgumentNullException(nameof(dto)); await _validation.NotEmpty(dto.ApiKey, nameof(dto.ApiKey)); await _validation.NotEmpty(dto.ApiName, nameof(dto.ApiName)); dto.TenantId = login.ClientId; bool isNew = dto.ApiId == 0; long apiId; if (isNew) { var autoNumberDTO = await _autoNumber.GetAutoNumber(1, "API", login); dto.ApiId = autoNumberDTO.StartNumber; apiId = await _dal.SaveAPIAsync(dto, login, ct); } else { apiId = await _dal.UpdateAPIAsync(dto, login, ct); } var cacheKey = new CacheKeyGeneration().KeyGeneration( login.ClientId.ToString(), Constant.EntityConstant.OBJECTAMPAPI, Constant.CacheKeyLevel.CLIENT_LEVEL, login); try { await _keyInvalidate.InvalidateCache(cacheKey); } catch (Exception ex) { _logger.LogWarning(ex, "Dapr cache invalidation failed for API {ApiId}", apiId); } try { await _eventLog.PublishEventLogAsync( isNew ? "AMP API Registered" : "AMP API Updated", new { dto.ApiKey, dto.ApiName, apiId }, Constant.EventTypeConstant.SAVEDOCUMENTSET, 0, login); } catch (Exception ex) { _logger.LogWarning(ex, "Dapr event publish failed for API {ApiId}", apiId); } return isNew ? $"{SuccessResponse.SaveSuccessMessage} {apiId}" : $"{SuccessResponse.UpdateSuccessMessage} {apiId}"; } // ===================================================== // LIFECYCLE // ===================================================== public async Task UpdateLifecycleAsync(long APIId, int lifecycleStatus, LoginDTO login, CancellationToken ct) { var modifiedById = login.UserId; await _dal.UpdateLifecycleAsync(APIId, login.ClientId, lifecycleStatus, modifiedById, login, ct); var cacheKey = new CacheKeyGeneration().KeyGeneration( login.ClientId.ToString(), Constant.EntityConstant.OBJECTAMPAPI, Constant.CacheKeyLevel.CLIENT_LEVEL, login); try { await _keyInvalidate.InvalidateCache(cacheKey); } catch (Exception ex) { _logger.LogWarning(ex, "Dapr cache invalidation failed for API lifecycle {APIId}", APIId); } try { await _eventLog.PublishEventLogAsync( "AMP API Lifecycle Updated", new { APIId, LifecycleStatus = lifecycleStatus }, Constant.EventTypeConstant.SAVEDOCUMENTSET, 0, login); } catch (Exception ex) { _logger.LogWarning(ex, "Dapr event publish failed for API lifecycle {APIId}", APIId); } return $"{SuccessResponse.UpdateSuccess} {APIId}"; } }