using FastEndpoints; using FrameworkBLL.EIPConversation; using FrameworkDAL.DTO.EIPConversation; using GB5Shared.DTO.Framework.Login; using GB5Shared.DTO.Framework.ResponseStandard; using GB5Shared.FastEndPoint; using Microsoft.Extensions.Logging; using System; using System.Text.Json; using System.Threading; using System.Threading.Tasks; using static GB5Shared.GB5Constant.Constant; namespace FrameworkSL.Endpoints.EIPConversation { /// /// Universal Webhook Endpoint /// Supports: Telegram, Teams, WhatsApp, Slack, Postman, etc. /// Always converts to standard MessageHubInboundDTO (3 fields) /// public class EIPConcept : BaseEndpoint> { private readonly ILogger _logger; private readonly IEIPConceptBLL _bll; public EIPConcept( ILogger logger, IEIPConceptBLL bll) { _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _bll = bll ?? throw new ArgumentNullException(nameof(bll)); } public override void Configure() { Post("/api/messagehub/webhook"); AllowAnonymous(); } #region Request Parameters public record ReceiveParameters( [property: FromHeader] string? Login, [property: FromBody] object RawBody ); #endregion protected override async Task> ExecuteAsync( ReceiveParameters req, LoginDTO loginDTO, CancellationToken ct) { try { loginDTO ??= new LoginDTO { UserId = 0, UserName = "external", ClientId = -1 }; // Serialize raw incoming JSON var rawJson = JsonSerializer.Serialize(req.RawBody); var inbound = NormalizeInboundPayload(rawJson); _logger.LogInformation( "Incoming message | Platform={Platform} | From={From} | Message={Message}", inbound.Platform, inbound.From, inbound.Message); // Send to BLL (always 3-field standard DTO) string reply = await _bll.HandleIncomingMessageAsync( sessionToken: inbound.From, userMessage: inbound.Message, loginContext: loginDTO, // ✅ use loginContext platformName: inbound.Platform, ct: ct ); _logger.LogInformation( "Outgoing reply | Platform={Platform} | To={From} | Message={Reply}", inbound.Platform, inbound.From, reply); return await GB5Shared.ResponseStandard.Response .CreateSuccessResponse(reply, CacheKeyLevel.NOT_REQUIRED, loginDTO); } catch (Exception ex) { _logger.LogError(ex, "Webhook processing failed"); return await GB5Shared.ResponseStandard.Response .CreateExceptionError( ex, CacheKeyLevel.NOT_REQUIRED, loginDTO, ex.Message, 500); } } /// /// Normalizes all platform payloads into standard MessageHubInboundDTO /// private MessageHubInboundDTO NormalizeInboundPayload(string rawJson) { var inbound = new MessageHubInboundDTO(); // 🔹 TELEGRAM if (rawJson.Contains("\"update_id\"")) { var telegram = JsonSerializer.Deserialize(rawJson); inbound.Message = telegram?.Message?.Text ?? string.Empty; inbound.From = telegram?.Message?.Chat?.Id.ToString() ?? "unknown"; inbound.Platform = "TELEGRAM"; } // 🔹 STANDARD (Postman / Internal) else if (rawJson.Contains("\"Message\"") && rawJson.Contains("\"Platform\"")) { inbound = JsonSerializer.Deserialize(rawJson) ?? new MessageHubInboundDTO(); } // 🔹 TEAMS (Basic example) else if (rawJson.Contains("\"type\"") && rawJson.Contains("\"conversation\"")) { var teams = JsonSerializer.Deserialize(rawJson); inbound.Message = teams?.Text ?? string.Empty; inbound.From = teams?.From?.Id ?? "unknown"; inbound.Platform = "TEAMS"; } // 🔹 WHATSAPP (Meta Webhook Example) else if (rawJson.Contains("\"entry\"") && rawJson.Contains("\"changes\"")) { var whatsapp = JsonSerializer.Deserialize(rawJson); inbound.Message = whatsapp?.GetMessageText() ?? string.Empty; inbound.From = whatsapp?.GetSender() ?? "unknown"; inbound.Platform = "WHATSAPP"; } else { inbound.Platform = "UNKNOWN"; inbound.Message = string.Empty; inbound.From = "unknown"; } return inbound; } } #region Telegram Models public class TelegramUpdate { public long Update_Id { get; set; } public TelegramMessage? Message { get; set; } } public class TelegramMessage { public TelegramChat? Chat { get; set; } public string? Text { get; set; } } public class TelegramChat { public long Id { get; set; } } #endregion #region Teams Models (Simplified) public class TeamsUpdate { public string? Text { get; set; } public TeamsFrom? From { get; set; } } public class TeamsFrom { public string? Id { get; set; } } #endregion #region WhatsApp Models (Simplified Placeholder) public class WhatsAppUpdate { public string? GetMessageText() => string.Empty; // implement actual mapping public string? GetSender() => string.Empty; // implement actual mapping } #endregion }