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<TextConversionApiController> _logger;
        private readonly IAsyncPolicy<string> _retryPolicy;

        public TextConversionApiController(ILogger<TextConversionApiController> logger)
        {
            _logger = logger;
            
            // Configurar política de retry com Polly
            _retryPolicy = Policy
                .Handle<Exception>()
                .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<string>();
        }

        [HttpPost("sentence-case")]
        public async Task<IActionResult> 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<IActionResult> 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<IActionResult> 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<string, string>? 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<string, object>? Metadata { get; set; }
    }
}