using FrameworkBLL.EIPConversation.EIPHandlers.EIPConversationBLL;
using FrameworkDAL.DTO.EIPConversation;
using FrameworkDAL.DTO.MessageHub;
using GB5Shared.DTO.Framework.Login;
using Microsoft.Extensions.Logging;
namespace FrameworkBLL.EIPConversation.EIPHandlers.EIPWebhook
{
///
/// Webhook Orchestrator
/// Handles incoming external messages (WhatsApp, etc.)
/// and forwards to Conversation Engine
///
public class EIPWebhookBLL : IEIPWebhookBLL
{
private readonly IEIPConversationBLL _conversationBLL;
private readonly ILogger _logger;
public EIPWebhookBLL(
IEIPConversationBLL conversationBLL,
ILogger logger)
{
_conversationBLL = conversationBLL
?? throw new ArgumentNullException(nameof(conversationBLL));
_logger = logger
?? throw new ArgumentNullException(nameof(logger));
}
///
/// Main webhook entry point
///
public async Task HandleWebhookAsync(
MessageHubWebhookDTO webhookDTO,
LoginDTO loginDTO,
CancellationToken cancellationToken)
{
if (webhookDTO == null)
throw new ArgumentNullException(nameof(webhookDTO));
if (loginDTO == null)
throw new ArgumentNullException(nameof(loginDTO));
try
{
var messages = webhookDTO.Messages ?? new List();
_logger.LogInformation(
"WEBHOOK START | MessageCount={Count} | Tenant={Tenant}",
messages.Count,
loginDTO.ClientId);
foreach (var msg in messages)
{
if (msg == null)
continue;
var content = ExtractMessageContent(msg);
if (string.IsNullOrWhiteSpace(msg.From))
{
_logger.LogWarning("Skipping message with empty sender.");
continue;
}
if (string.IsNullOrWhiteSpace(content))
{
_logger.LogWarning(
"Skipping empty message | From={From} | Type={Type}",
msg.From,
msg.Type);
continue;
}
// ✅ FIXED DTO MAPPING
var conversationDTO = new EIPConversationDTO
{
TenantId = loginDTO.ClientId, // ✅ FIX 1
ChannelType = EIPChannelType.WhatsApp, // ✅ FIX 2
Channel = "WHATSAPP", // ✅ string channel for handlers
UserIdentifier = msg.From,
Message = content
};
_logger.LogInformation(
"FORWARD TO ENGINE | User={User} | Message={Message}",
conversationDTO.UserIdentifier,
conversationDTO.Message);
var result = await _conversationBLL.HandleIncomingConversationAsync(
conversationDTO,
loginDTO,
cancellationToken);
_logger.LogInformation(
"ENGINE RESPONSE | User={User} | Step={Step}",
conversationDTO.UserIdentifier,
result?.CurrentStepCode);
}
_logger.LogInformation("WEBHOOK COMPLETE");
}
catch (Exception ex)
{
_logger.LogError(ex,
"WEBHOOK ERROR | Tenant={Tenant}",
loginDTO.ClientId);
throw;
}
}
///
/// Extract message content from webhook
/// Supports:
/// - text
/// - button
/// - interactive (list / reply)
///
private static string ExtractMessageContent(MessageWebhookDTO msg)
{
if (msg == null)
return string.Empty;
return msg.Type?.ToLower() switch
{
"text" => msg.Text?.Body ?? string.Empty,
"button" => msg.Button?.Text
?? msg.Button?.Payload
?? string.Empty,
"interactive" => msg.Interactive?.ButtonReply?.Title
?? msg.Interactive?.ListReply?.Title
?? string.Empty,
_ => string.Empty
};
}
}
}