using FrameworkDAL.DTO.EIPConversation;
using GB5Shared.DTO.Framework.Login;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace FrameworkBLL.EIPConversation.EIPHandlers.EIPEngine.ActionHandler
{
///
/// Updates a CRM call record's status by posting to the CRM service API.
/// Reads CallId and ApprovalStatus from context.Payload.
/// Base URL comes from SysJobSettings:ServiceBaseUrl (same as WebhookEndpointResolver).
///
public class CallStatusUpdateAction : IEIPActionHandler
{
public string ActionCode => "CALL_STATUS_UPDATE";
private readonly IHttpClientFactory _httpClientFactory;
private readonly IConfiguration _config;
private readonly ILogger _logger;
public CallStatusUpdateAction(
IHttpClientFactory httpClientFactory,
IConfiguration config,
ILogger logger)
{
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException(nameof(httpClientFactory));
_config = config ?? throw new ArgumentNullException(nameof(config));
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public bool CanHandle(string actionName)
=> string.Equals(actionName, ActionCode, StringComparison.OrdinalIgnoreCase);
public async Task HandleAsync(
EIPActionContextDTO context,
LoginDTO loginDTO,
CancellationToken ct)
{
if (context.Payload == null || context.Payload.Count == 0)
return new EIPActionResultDTO { IsSuccess = false, Message = "Payload is empty." };
if (!context.Payload.TryGetValue("CallId", out var callIdObj) ||
!context.Payload.TryGetValue("ApprovalStatus", out var statusObj))
{
return new EIPActionResultDTO { IsSuccess = false, Message = "Required keys 'CallId' and 'ApprovalStatus' missing in payload." };
}
if (!int.TryParse(callIdObj?.ToString(), out var callId) || callId <= 0)
return new EIPActionResultDTO { IsSuccess = false, Message = "CallId must be a positive integer." };
if (!int.TryParse(statusObj?.ToString(), out var approvalStatus))
return new EIPActionResultDTO { IsSuccess = false, Message = "ApprovalStatus must be an integer." };
var baseUrl = _config["SysJobSettings:ServiceBaseUrl"]?.TrimEnd('/');
if (string.IsNullOrWhiteSpace(baseUrl))
{
_logger.LogError("CallStatusUpdateAction: SysJobSettings:ServiceBaseUrl is not configured.");
return new EIPActionResultDTO { IsSuccess = false, Message = "Service base URL is not configured." };
}
var endpoint = $"{baseUrl}/Call/UpdateCallStatus";
_logger.LogInformation(
"CallStatusUpdateAction: POST {Endpoint} | CallId={CallId} Status={Status}",
endpoint, callId, approvalStatus);
try
{
var requestBody = JsonSerializer.Serialize(new
{
CallId = callId,
ApprovalStatus = approvalStatus,
UpdatedById = loginDTO.UserId
});
var client = _httpClientFactory.CreateClient("crm-internal");
using var content = new StringContent(requestBody, Encoding.UTF8, "application/json");
var response = await client.PostAsync(endpoint, content, ct).ConfigureAwait(false);
var responseBody = await response.Content.ReadAsStringAsync(ct).ConfigureAwait(false);
if (!response.IsSuccessStatusCode)
{
_logger.LogWarning(
"CallStatusUpdateAction: {Status} from CRM | CallId={CallId} Body={Body}",
(int)response.StatusCode, callId, responseBody);
return new EIPActionResultDTO
{
IsSuccess = false,
Message = $"CRM service returned {(int)response.StatusCode}.",
ErrorMessage = responseBody
};
}
_logger.LogInformation(
"CallStatusUpdateAction: Call {CallId} updated to status {Status}", callId, approvalStatus);
return new EIPActionResultDTO
{
IsSuccess = true,
Message = $"Call {callId} updated successfully."
};
}
catch (OperationCanceledException)
{
_logger.LogWarning("CallStatusUpdateAction: cancelled | CallId={CallId}", callId);
return new EIPActionResultDTO { IsSuccess = false, Message = "Operation cancelled." };
}
catch (Exception ex)
{
_logger.LogError(ex, "CallStatusUpdateAction: exception | CallId={CallId}", callId);
return new EIPActionResultDTO { IsSuccess = false, Message = ex.Message, ErrorMessage = ex.ToString() };
}
}
}
}