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; } }