using FrameworkBLL.EIPConversation.EIPHandlers.EIPEngine.ActionHandler; using FrameworkDAL.DTO.EIPConversation; using GB5Shared.DTO.Framework.Login; using Microsoft.Extensions.Logging; namespace FrameworkBLL.EIPConversation.EIPHandlers.EIPActionExecutor { public class EIPActionExecutor : IEIPActionExecutor { private readonly IReadOnlyDictionary _handlerMap; private readonly IReadOnlyList _wildcardHandlers; private readonly ILogger _logger; public EIPActionExecutor(IEnumerable handlers, ILogger logger) { if (handlers == null) throw new ArgumentNullException(nameof(handlers)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); // Separate exact-match handlers from wildcard handlers (ActionCode = "") var exactHandlers = handlers.Where(h => !string.IsNullOrEmpty(h.ActionCode)).ToList(); var wildcardHandlers = handlers.Where(h => string.IsNullOrEmpty(h.ActionCode)).ToList(); // Detect duplicate exact-match ActionCodes var grouped = exactHandlers .GroupBy(h => h.ActionCode, StringComparer.OrdinalIgnoreCase) .ToList(); var duplicates = grouped.Where(g => g.Count() > 1).Select(g => g.Key).ToList(); if (duplicates.Any()) { var dupList = string.Join(", ", duplicates); _logger.LogError("Duplicate IEIPActionHandler implementations detected for ActionCodes: {Duplicates}", dupList); throw new InvalidOperationException($"Duplicate IEIPActionHandler implementations found for ActionCodes: {dupList}"); } _handlerMap = grouped.ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase); _wildcardHandlers = wildcardHandlers.AsReadOnly(); _logger.LogInformation("EIPActionExecutor initialized with {Exact} exact + {Wild} wildcard handlers.", _handlerMap.Count, _wildcardHandlers.Count); } public async Task ExecuteAsync( string actionName, EIPActionContextDTO context, LoginDTO loginDTO, CancellationToken ct = default) { if (string.IsNullOrWhiteSpace(actionName)) throw new ArgumentException("Action name cannot be empty.", nameof(actionName)); if (context == null) throw new ArgumentNullException(nameof(context)); if (loginDTO == null) throw new ArgumentNullException(nameof(loginDTO)); try { _logger.LogInformation("Executing EIP Action: {ActionName}", actionName); if (!_handlerMap.TryGetValue(actionName, out var handler)) { handler = _wildcardHandlers.FirstOrDefault(h => h.CanHandle(actionName)); if (handler == null) throw new InvalidOperationException($"No action handler found for action: {actionName}"); } return await handler.HandleAsync(context, loginDTO, ct); } catch (Exception ex) { _logger.LogError(ex, "Error executing action: {ActionName}", actionName); throw; } } } }