using Microsoft.AspNetCore.Mvc; using System.Text.RegularExpressions; using System.Text; using Polly; using Polly.Extensions.Http; namespace OnlyOneAccessTemplate.Controllers { [ApiController] [Route("api/text-conversion")] public class TextConversionApiController : ControllerBase { private readonly ILogger _logger; private readonly IAsyncPolicy _retryPolicy; public TextConversionApiController(ILogger logger) { _logger = logger; // Configurar política de retry com Polly _retryPolicy = Policy .Handle() .WaitAndRetryAsync( retryCount: 3, sleepDurationProvider: retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt)), onRetry: (outcome, timespan, retryCount, context) => { _logger.LogWarning("Tentativa {RetryCount} de conversão de texto após {Delay}ms. Erro: {Error}", retryCount, timespan.TotalMilliseconds, outcome.Message); }) .AsAsyncPolicy(); } [HttpPost("sentence-case")] public async Task ConvertToSentenceCase([FromBody] TextConversionRequest request) { try { if (string.IsNullOrEmpty(request.Text)) { return BadRequest(new { success = false, message = "Texto não pode estar vazio" }); } // Aplicar política de retry var result = await _retryPolicy.ExecuteAsync(async () => { return await Task.FromResult(ConvertToSentenceCase(request.Text)); }); _logger.LogInformation("Conversão de texto realizada com sucesso para {Length} caracteres", request.Text.Length); return Ok(new TextConversionResponse { Success = true, OriginalText = request.Text, ConvertedText = result, ProcessedAt = DateTime.UtcNow }); } catch (Exception ex) { _logger.LogError(ex, "Erro ao converter texto para sentence case"); return StatusCode(500, new { success = false, message = "Erro interno do servidor" }); } } [HttpPost("upper-case")] public async Task ConvertToUpperCase([FromBody] TextConversionRequest request) { try { if (string.IsNullOrEmpty(request.Text)) { return BadRequest(new { success = false, message = "Texto não pode estar vazio" }); } var result = await _retryPolicy.ExecuteAsync(async () => { return await Task.FromResult(request.Text.ToUpper()); }); return Ok(new TextConversionResponse { Success = true, OriginalText = request.Text, ConvertedText = result, ProcessedAt = DateTime.UtcNow }); } catch (Exception ex) { _logger.LogError(ex, "Erro ao converter texto para maiúsculas"); return StatusCode(500, new { success = false, message = "Erro interno do servidor" }); } } [HttpPost("lower-case")] public async Task ConvertToLowerCase([FromBody] TextConversionRequest request) { try { if (string.IsNullOrEmpty(request.Text)) { return BadRequest(new { success = false, message = "Texto não pode estar vazio" }); } var result = await _retryPolicy.ExecuteAsync(async () => { return await Task.FromResult(request.Text.ToLower()); }); return Ok(new TextConversionResponse { Success = true, OriginalText = request.Text, ConvertedText = result, ProcessedAt = DateTime.UtcNow }); } catch (Exception ex) { _logger.LogError(ex, "Erro ao converter texto para minúsculas"); return StatusCode(500, new { success = false, message = "Erro interno do servidor" }); } } [HttpGet("health")] public IActionResult HealthCheck() { return Ok(new { status = "healthy", timestamp = DateTime.UtcNow }); } private string ConvertToSentenceCase(string text) { if (string.IsNullOrEmpty(text)) return text; // Converte todo o texto para minúsculas primeiro string lowerText = text.ToLower(); // StringBuilder para construir o resultado StringBuilder result = new StringBuilder(lowerText); // Capitaliza a primeira letra do texto se for uma letra if (result.Length > 0 && char.IsLetter(result[0])) { result[0] = char.ToUpper(result[0]); } // Regex para encontrar início de frases/parágrafos // Procura por pontos, exclamações, interrogações ou quebras de linha // seguidos por espaços e uma letra string pattern = @"([.!?\n]\s*)([a-z])"; string resultText = result.ToString(); resultText = Regex.Replace(resultText, pattern, match => { return match.Groups[1].Value + char.ToUpper(match.Groups[2].Value[0]); }); return resultText; } } public class TextConversionRequest { public string Text { get; set; } = string.Empty; public string? Language { get; set; } public Dictionary? Options { get; set; } } public class TextConversionResponse { 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; } } }