using OnlyOneAccessTemplate.Models; using OnlyOneAccessTemplate.Services.OnlyOneAccessTemplate.Services; using Polly; using Polly.Extensions.Http; using System.Text; using System.Text.Json; namespace OnlyOneAccessTemplate.Services { public interface ITextConversionApiService { Task ConvertToSentenceCaseAsync(string text); Task ConvertToUpperCaseAsync(string text); Task ConvertToLowerCaseAsync(string text); Task IsHealthyAsync(); } public class TextConversionApiService : ITextConversionApiService { private readonly HttpClient _httpClient; private readonly ILogger _logger; private readonly IAsyncPolicy _retryPolicy; private readonly string _baseUrl; public TextConversionApiService( HttpClient httpClient, ILogger logger, IConfiguration configuration) { _httpClient = httpClient; _logger = logger; _baseUrl = configuration.GetValue("TextConversionApi:BaseUrl") ?? "https://localhost:7071"; // Configurar política de retry com Polly para HttpClient _retryPolicy = HttpPolicyExtensions .HandleTransientHttpError() .OrResult(msg => !msg.IsSuccessStatusCode) .WaitAndRetryAsync( retryCount: 3, sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), onRetry: (outcome, timespan, retryCount, context) => { _logger.LogWarning("Tentativa {RetryCount} de chamada à API após {Delay}ms. Status: {StatusCode}", retryCount, timespan.TotalMilliseconds, outcome.Result?.StatusCode); }); // Configurar timeout _httpClient.Timeout = TimeSpan.FromSeconds(30); } public async Task ConvertToSentenceCaseAsync(string text) { try { var request = new { Text = text }; var response = await CallApiAsync("/api/text-conversion/sentence-case", request); return response.ConvertedText; } catch (Exception ex) { _logger.LogError(ex, "Erro ao converter texto para sentence case via API"); throw; } } public async Task ConvertToUpperCaseAsync(string text) { try { var request = new { Text = text }; var response = await CallApiAsync("/api/text-conversion/upper-case", request); return response.ConvertedText; } catch (Exception ex) { _logger.LogError(ex, "Erro ao converter texto para maiúsculas via API"); throw; } } public async Task ConvertToLowerCaseAsync(string text) { try { var request = new { Text = text }; var response = await CallApiAsync("/api/text-conversion/lower-case", request); return response.ConvertedText; } catch (Exception ex) { _logger.LogError(ex, "Erro ao converter texto para minúsculas via API"); throw; } } public async Task IsHealthyAsync() { try { var response = await _retryPolicy.ExecuteAsync(async () => { return await _httpClient.GetAsync($"{_baseUrl}/api/text-conversion/health"); }); return response.IsSuccessStatusCode; } catch (Exception ex) { _logger.LogError(ex, "Erro ao verificar saúde da API de conversão de texto"); return false; } } private async Task CallApiAsync(string endpoint, object request) { var json = JsonSerializer.Serialize(request); var content = new StringContent(json, Encoding.UTF8, "application/json"); var response = await _retryPolicy.ExecuteAsync(async () => { return await _httpClient.PostAsync($"{_baseUrl}{endpoint}", content); }); if (!response.IsSuccessStatusCode) { var errorContent = await response.Content.ReadAsStringAsync(); throw new HttpRequestException($"API call failed with status {response.StatusCode}: {errorContent}"); } var responseContent = await response.Content.ReadAsStringAsync(); var result = JsonSerializer.Deserialize(responseContent, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); if (result == null || !result.Success) { throw new InvalidOperationException($"API returned unsuccessful response: {result?.ErrorMessage}"); } return result; } } public class TextConversionApiResponse { public bool Success { get; set; } public string OriginalText { get; set; } = string.Empty; public string ConvertedText { get; set; } = string.Empty; public DateTime ProcessedAt { get; set; } public string? ErrorMessage { get; set; } public Dictionary? Metadata { get; set; } } // Novo serviço que substitui o UpperLowerConversorService usando a API public class ApiBasedSentenceConverterService : BaseConverterService { private readonly ITextConversionApiService _apiService; public override string ConverterType => "text-case-sentence"; public override string ConverterName => "Maiúsculas para minúsculas"; public ApiBasedSentenceConverterService( ILogger logger, IConfiguration configuration, ITextConversionApiService apiService) : base(logger, configuration) { _apiService = apiService; } public override async Task ConvertAsync(ConversionRequest request) { try { var resultado = await _apiService.ConvertToSentenceCaseAsync(request.TextInput); return new ConversionResult(true, OutputText: resultado); } catch (Exception ex) { _logger.LogError(ex, "Erro na conversão via API"); return new ConversionResult(false, ErrorMessage: "Erro ao processar via API"); } } public override ConverterConfiguration GetConfiguration(string language) { var texts = GetLocalizedTexts(language); texts["ConverterTitle"] = language switch { "en" => "Sentence Case Convert", "es" => "Convertir a Mayúscula Inicial", _ => "Converter para primeira maiúscula" }; return new ConverterConfiguration { ConverterType = "text", OutputType = "text", HasAdvancedOptions = false, AllowShare = true, LocalizedTexts = texts }; } } }