using FrameworkDAL.CustomCode.EIPConversation.EIPRoutingAdmin; using FrameworkDAL.DTO.EIPConversation; using GB5Shared.DTO.Framework.Login; using GB5Shared.Resource.Response; using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; namespace FrameworkBLL.EIPConversation.EIPAdmin.EIPRoutingAdmin { public class EIPRoutingAdminBLL : IEIPRoutingAdminBLL { private readonly IEIPRoutingAdminDAL _dal; private readonly ILogger _logger; public EIPRoutingAdminBLL( IEIPRoutingAdminDAL dal, ILogger logger) { _dal = dal ?? throw new ArgumentNullException(nameof(dal)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } // ===================================================== // GET LIST // ===================================================== public async Task> GetRouteListAsync( int? channelType, LoginDTO login, CancellationToken ct = default) { try { _logger.LogInformation( "BLL | GetRouteList | Tenant={TenantId} | ChannelType={ChannelType}", login.ClientId, channelType); return await _dal.GetRouteListAsync(channelType, login, ct).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError(ex, "BLL | GetRouteList | Error | Tenant={TenantId}", login.ClientId); throw; } } // ===================================================== // GET SINGLE // ===================================================== public async Task GetRouteAsync( int routingRuleId, LoginDTO login, CancellationToken ct = default) { try { _logger.LogInformation( "BLL | GetRoute | Tenant={TenantId} | RoutingRuleId={RoutingRuleId}", login.ClientId, routingRuleId); return await _dal.GetRouteAsync(routingRuleId, login, ct).ConfigureAwait(false); } catch (Exception ex) { _logger.LogError(ex, "BLL | GetRoute | Error | RoutingRuleId={RoutingRuleId}", routingRuleId); throw; } } // ===================================================== // SAVE (INSERT or UPDATE) // ===================================================== public async Task SaveRouteAsync( EIPRoutingRuleAdminDTO dto, LoginDTO login, CancellationToken ct = default) { try { // ── Validate ────────────────────────────────────────── _logger.LogInformation( "BLL | SaveRoute | Validate | Tenant={TenantId} | FlowId={FlowId}", login.ClientId, dto.FlowId); // AutoNumber-generated ids in this repo are negative (e.g. -1210050000) — only 0 // (the C# default, meaning "never set") is genuinely invalid here. if (dto.FlowId == 0) throw new ArgumentException("FlowId must reference a valid flow definition."); // MEIPROUTINGRULE.CHANNELTYPE is NOT NULL — the DTO's nullable int? was never // validated, so omitting it inserted an explicit NULL (bypassing the column's // own DEFAULT, which only applies when the column is omitted from the INSERT // entirely, not when NULL is passed for it) and threw a raw SQL error. if (!dto.ChannelType.HasValue) throw new ArgumentException("ChannelType is required."); if (dto.PriorityOrder < 1) throw new ArgumentException("PriorityOrder must be >= 1."); if (dto.MatchType < 1 || dto.MatchType > 4) throw new ArgumentException( "MatchType must be 1=EQUALS, 2=STARTS_WITH, 3=CONTAINS, or 4=REGEX."); if (string.IsNullOrWhiteSpace(dto.Pattern)) throw new ArgumentException("Pattern is required."); dto.TenantId = login.ClientId; var isNew = dto.RoutingRuleId == 0; // ── Persist ─────────────────────────────────────────── _logger.LogInformation( "BLL | SaveRoute | Persist | Tenant={TenantId} | IsNew={IsNew}", login.ClientId, isNew); if (isNew) { var newId = await _dal.InsertRouteAsync(dto, login, ct).ConfigureAwait(false); _logger.LogInformation( "BLL | SaveRoute | Inserted | NewId={NewId}", newId); return $"{SuccessResponse.SaveSuccessMessage} {newId}"; } else { await _dal.UpdateRouteAsync(dto, login, ct).ConfigureAwait(false); _logger.LogInformation( "BLL | SaveRoute | Updated | RoutingRuleId={Id}", dto.RoutingRuleId); return SuccessResponse.UpdateSuccess; } } catch (Exception ex) { _logger.LogError(ex, "BLL | SaveRoute | Error | Tenant={TenantId} | RoutingRuleId={Id}", login.ClientId, dto.RoutingRuleId); throw; } } // ===================================================== // DELETE // ===================================================== public async Task DeleteRouteAsync( int routingRuleId, LoginDTO login, CancellationToken ct = default) { try { _logger.LogInformation( "BLL | DeleteRoute | Tenant={TenantId} | RoutingRuleId={RoutingRuleId}", login.ClientId, routingRuleId); if (routingRuleId == 0) throw new ArgumentException("RoutingRuleId must be a positive integer."); await _dal.DeleteRouteAsync(routingRuleId, login, ct).ConfigureAwait(false); _logger.LogInformation( "BLL | DeleteRoute | Completed | RoutingRuleId={RoutingRuleId}", routingRuleId); return SuccessResponse.DeleteSuccessMessage; } catch (Exception ex) { _logger.LogError(ex, "BLL | DeleteRoute | Error | RoutingRuleId={RoutingRuleId}", routingRuleId); throw; } } } }