using FastEndpoints;
using FrameworkBLL.EIPConversation.EIPHandlers.EIPConversationBLL;
using FrameworkDAL.DTO.EIPConversation;
using GB5Shared.DTO.Framework.Login;
using GB5Shared.DTO.Framework.ResponseStandard;
using GB5Shared.FastEndPoint;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using static GB5Shared.GB5Constant.Constant;
namespace FrameworkSL.Endpoints.EIPConversation
{
///
/// Inbound entry point for the Voice channel (Twilio, Azure Bot, Google Dialogflow, etc.).
/// The calling voice platform is responsible for its own speech-to-text; it posts the
/// transcribed text here exactly like any other channel, with ChannelType=Voice (7).
/// The response's ResponseMessage/VoiceHint fields carry the TTS/SSML text back for the
/// platform to synthesise — mirrors VoiceChannelHandler's AdditionalData shape.
///
public class ReceiveVoice
: BaseEndpoint>
{
private readonly IEIPConversationBLL _conversationService;
private readonly ILogger _logger;
public ReceiveVoice(
IEIPConversationBLL conversationService,
ILogger logger)
{
_conversationService = conversationService;
_logger = logger;
}
public override void Configure()
{
Post("/EIPConversation/ReceiveVoice");
AllowAnonymous(); // Voice platform webhook entry
}
public record ReceiveVoiceParameters(
[property: FromHeader] string Login,
[property: FromBody] EIPConversationDTO Payload
);
protected override async Task> ExecuteAsync(
ReceiveVoiceParameters req,
LoginDTO loginDTO,
CancellationToken ct)
{
var correlationId = Guid.NewGuid().ToString("N");
var stopwatch = Stopwatch.StartNew();
try
{
if (req.Payload == null)
throw new ArgumentNullException(nameof(req.Payload));
// Voice platforms don't know about EIPChannelType — force it here rather than
// trusting the caller to set it, same reasoning as AppChat/DirectAction channels.
req.Payload.ChannelType = EIPChannelType.Voice;
_logger.LogInformation(
"EIP VOICE START | CorrelationId={CorrelationId} | Tenant={Tenant} | User={User} | Message={Message}",
correlationId,
req.Payload.TenantId,
req.Payload.UserIdentifier,
req.Payload.Message);
var result = await _conversationService
.HandleIncomingConversationAsync(req.Payload, loginDTO!, ct);
stopwatch.Stop();
_logger.LogInformation(
"EIP VOICE END | CorrelationId={CorrelationId} | Tenant={Tenant} | FinalStep={Step} | DurationMs={Duration}",
correlationId,
req.Payload.TenantId,
result?.CurrentStepCode,
stopwatch.ElapsedMilliseconds);
return await GB5Shared.ResponseStandard.Response
.CreateSuccessResponse(result, CacheKeyLevel.NOT_REQUIRED, loginDTO);
}
catch (Exception ex)
{
stopwatch.Stop();
_logger.LogError(
ex,
"EIP VOICE ERROR | CorrelationId={CorrelationId} | Tenant={Tenant} | DurationMs={Duration}",
correlationId,
req?.Payload?.TenantId,
stopwatch.ElapsedMilliseconds);
return await GB5Shared.ResponseStandard.Response
.CreateExceptionError(
ex,
CacheKeyLevel.NOT_REQUIRED,
loginDTO,
ex.Message,
500);
}
}
}
}