using GB5Shared.ActionProcessor;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Threading;
using System.Threading.Tasks;
using Twilio.Rest.Api.V2010.Account;
using Twilio.Types;
namespace FrameworkBLL.ActionProcessor.Handlers
{
///
/// ActionType = 1 (SMS). Sends SMS via Twilio.
/// Twilio credentials must be configured in appsettings.json.
///
public sealed class SmsActionHandler : IActionHandler
{
public int ActionType => 1;
private readonly string? _fromNumber;
private readonly ILogger _logger;
public SmsActionHandler(
IOptions smsSettings,
ILogger logger)
{
_fromNumber = smsSettings?.Value?.FromNumber;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
if (string.IsNullOrWhiteSpace(_fromNumber))
_logger.LogWarning("SmsActionHandler: Twilio FromNumber is not configured — SMS actions will fail at runtime.");
}
public async Task HandleAsync(ActionEventDto dto, CancellationToken ct = default)
{
if (dto == null)
return ActionResult.Permanent("ActionEventDto cannot be null");
if (string.IsNullOrWhiteSpace(_fromNumber))
return ActionResult.Permanent("Twilio FromNumber is not configured.");
if (string.IsNullOrWhiteSpace(dto.SendTo))
{
_logger.LogWarning(
"SMS handler validation failed | ActionRunId={ActionRunId} SendTo missing",
dto.ActionRunId);
return ActionResult.Permanent("SendTo is required for SMS actions");
}
try
{
var message = await MessageResource.CreateAsync(
body: dto.Payload.ToString() ?? string.Empty,
from: new PhoneNumber(_fromNumber),
to: new PhoneNumber(dto.SendTo)
).ConfigureAwait(false);
_logger.LogInformation(
"SMS sent successfully | ActionRunId={ActionRunId} To={Recipient} Sid={Sid}",
dto.ActionRunId,
dto.SendTo,
message.Sid);
return ActionResult.Ok(message.Sid);
}
catch (Exception ex)
{
_logger.LogError(
ex,
"SMS handler exception | ActionRunId={ActionRunId}",
dto.ActionRunId);
return ActionResult.Transient(ex.Message);
}
}
}
///
/// SMS configuration settings.
///
public sealed class SmsSettings
{
public string FromNumber { get; set; } = string.Empty;
}
}