using Microsoft.Extensions.Caching.Distributed;
using QRCoder;
using QRRapidoApp.Models.ViewModels;
using System.Diagnostics;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Processing;
using SixLabors.ImageSharp.Formats.Png;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Drawing.Processing;
using System.Numerics;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Localization;

namespace QRRapidoApp.Services
{
    public class QRRapidoService : IQRCodeService
    {
        private readonly IDistributedCache _cache;
        private readonly IConfiguration _config;
        private readonly ILogger<QRRapidoService> _logger;
        private readonly SemaphoreSlim _semaphore;
        private readonly LogoReadabilityAnalyzer _readabilityAnalyzer;
        private readonly IStringLocalizer<QRRapidoApp.Resources.SharedResource> _localizer;

        public QRRapidoService(IDistributedCache cache, IConfiguration config, ILogger<QRRapidoService> logger, LogoReadabilityAnalyzer readabilityAnalyzer, IStringLocalizer<QRRapidoApp.Resources.SharedResource> localizer)
        {
            _cache = cache;
            _config = config;
            _logger = logger;
            _readabilityAnalyzer = readabilityAnalyzer;
            _localizer = localizer;

            // Limit simultaneous generations to maintain performance
            var maxConcurrent = _config.GetValue<int>("Performance:MaxConcurrentGenerations", 100);
            _semaphore = new SemaphoreSlim(maxConcurrent, maxConcurrent);
        }

        public async Task<QRGenerationResult> GenerateRapidAsync(QRGenerationRequest request)
        {
            var stopwatch = Stopwatch.StartNew();

            try
            {
                await _semaphore.WaitAsync();

                // Generate tracking ID for premium users with tracking enabled
                string? trackingId = null;
                string originalContent = request.Content;

                // DEBUG: Log all conditions
                _logger.LogInformation("[TRACKING DEBUG] IsPremium: {IsPremium}, EnableTracking: {EnableTracking}, Type: {Type}",
                    request.IsPremium, request.EnableTracking, request.Type);

                if (request.IsPremium && request.EnableTracking && request.Type == "url")
                {
                    // Only URL type QR codes can use tracking (redirect functionality)
                    trackingId = Guid.NewGuid().ToString("N").Substring(0, 12); // 12-char tracking ID
                    var baseUrl = _config.GetValue<string>("App:BaseUrl", "https://qrrapido.site");
                    request.Content = $"{baseUrl}/t/{trackingId}";

                    _logger.LogInformation("✅ Tracking enabled for QR - TrackingId: {TrackingId}, OriginalURL: {OriginalURL}",
                        trackingId, originalContent);
                }
                else
                {
                    _logger.LogWarning("❌ Tracking NOT enabled - IsPremium: {IsPremium}, EnableTracking: {EnableTracking}, Type: {Type}",
                        request.IsPremium, request.EnableTracking, request.Type);
                }

                // Cache key based on content and settings
                var cacheKey = GenerateCacheKey(request);
                var cached = await _cache.GetStringAsync(cacheKey);

                if (!string.IsNullOrEmpty(cached))
                {
                    stopwatch.Stop();
                    _logger.LogInformation($"QR code served from cache in {stopwatch.ElapsedMilliseconds}ms");

                    var cachedResult = JsonSerializer.Deserialize<QRGenerationResult>(cached);
                    if (cachedResult != null)
                    {
                        cachedResult.GenerationTimeMs = stopwatch.ElapsedMilliseconds;
                        cachedResult.FromCache = true;

                        // Se não tem análise de legibilidade no cache, gerar agora
                        if (cachedResult.ReadabilityInfo == null)
                        {
                            cachedResult.ReadabilityInfo = await _readabilityAnalyzer.AnalyzeAsync(request, request.Size);
                        }

                        return cachedResult;
                    }
                }

                // Optimized generation
                var qrCode = await GenerateQRCodeOptimizedAsync(request);

                // WebP conversion if requested
                var outputFormat = (request.OutputFormat ?? "png").ToLowerInvariant();
                byte[] finalBytes;
                if (outputFormat == "webp")
                    finalBytes = await ConvertPngBytesToWebPAsync(qrCode);
                else
                    finalBytes = qrCode;

                var base64 = Convert.ToBase64String(finalBytes);

                // Análise de legibilidade do logo
                var readabilityInfo = await _readabilityAnalyzer.AnalyzeAsync(request, request.Size);

                var result = new QRGenerationResult
                {
                    QRCodeBase64 = base64,
                    OutputFormat = outputFormat,
                    QRId = Guid.NewGuid().ToString(),
                    GenerationTimeMs = stopwatch.ElapsedMilliseconds,
                    FromCache = false,
                    Size = qrCode.Length,
                    RequestSettings = request,
                    Success = true,
                    ReadabilityInfo = readabilityInfo,
                    TrackingId = trackingId // Include tracking ID if enabled
                };

                // Restore original content if tracking was enabled
                if (trackingId != null)
                {
                    request.Content = originalContent;
                }

                // Cache for configurable time
                var cacheExpiration = TimeSpan.FromMinutes(_config.GetValue<int>("Performance:CacheExpirationMinutes", 60));
                await _cache.SetStringAsync(cacheKey, JsonSerializer.Serialize(result), new DistributedCacheEntryOptions
                {
                    AbsoluteExpirationRelativeToNow = cacheExpiration
                });

                stopwatch.Stop();
                _logger.LogInformation($"QR code generated in {stopwatch.ElapsedMilliseconds}ms for type {request.Type}");

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Error in rapid QR code generation: {ex.Message}");
                return new QRGenerationResult
                {
                    Success = false,
                    ErrorMessage = ex.Message,
                    GenerationTimeMs = stopwatch.ElapsedMilliseconds
                };
            }
            finally
            {
                _semaphore.Release();
            }
        }

        private async Task<byte[]> GenerateQRCodeOptimizedAsync(QRGenerationRequest request)
        {
            return await Task.Run(() =>
            {
                using var qrGenerator = new QRCodeGenerator();
                
                // CORREÇÃO 1: Usar nível de correção HIGH para logos
                var errorCorrectionLevel = request.HasLogo && request.Logo != null ? 
                    QRCodeGenerator.ECCLevel.H :  // 30% correção para logos
                    QRCodeGenerator.ECCLevel.M;   // 15% correção normal
                    
                using var qrCodeData = qrGenerator.CreateQrCode(request.Content, errorCorrectionLevel);

                // CORREÇÃO 2: Usar PngByteQRCode para compatibilidade
                using var qrCode = new PngByteQRCode(qrCodeData);

                var primaryColorBytes = ColorToBytes(ParseHtmlColor(request.PrimaryColor));
                var backgroundColorBytes = ColorToBytes(ParseHtmlColor(request.BackgroundColor));

                var pixelsPerModule = request.IsPremium ?
                    GetOptimalPixelsPerModule(request.Size) :
                    Math.Max(8, request.Size / 40);

                byte[] qrBytes;

                // CORREÇÃO 3: Para logos, usar implementação otimizada com alta correção de erro
                if (request.HasLogo && request.Logo != null)
                {
                    try
                    {
                        // Validar logo primeiro
                        if (!ValidateLogoForQR(request.Logo, out string errorMessage))
                        {
                            _logger.LogWarning("Logo validation failed: {ErrorMessage}, generating QR without logo", errorMessage);
                            // Fallback para QR sem logo
                            qrBytes = qrCode.GetGraphic(pixelsPerModule, primaryColorBytes, backgroundColorBytes);
                        }
                        else
                        {
                            // NOVO: Preprocessar logo (redimensionar se necessário)
                            var processedLogo = PreprocessLogo(request.Logo);
                            
                            // Gerar QR base com alta correção de erro
                            qrBytes = qrCode.GetGraphic(pixelsPerModule, primaryColorBytes, backgroundColorBytes);
                            
                            // CORREÇÃO 4: Aplicar logo processado com configurações aprimoradas
                            qrBytes = ApplyLogoOverlayEnhanced(qrBytes, processedLogo, request);

                            _logger.LogInformation("QR code with logo generated - Size: {LogoSize}%, Colorized: {IsColorized}", 
                                request.LogoSizePercent ?? 20, request.ApplyLogoColorization);
                        }
                    }
                    catch (Exception ex)
                    {
                        _logger.LogError(ex, "Error applying logo, falling back to no logo");
                        // Fallback para QR sem logo se der erro
                        qrBytes = qrCode.GetGraphic(pixelsPerModule, primaryColorBytes, backgroundColorBytes);
                    }
                }
                else
                {
                    // QR sem logo - usar correção padrão
                    qrBytes = qrCode.GetGraphic(pixelsPerModule, primaryColorBytes, backgroundColorBytes);
                }

                // CORREÇÃO 5: Aplicar estilos de canto APÓS o logo (se necessário)
                if (request.IsPremium && !string.IsNullOrEmpty(request.CornerStyle) && request.CornerStyle != "square")
                {
                    qrBytes = ApplyCornerStyle(qrBytes, request.CornerStyle, request.Size);
                }

                return qrBytes;
            });
        }

        private QRCodeGenerator.ECCLevel GetErrorCorrectionLevel(QRGenerationRequest request)
        {
            // Para logos, sempre usar correção HIGH
            if (request.HasLogo && request.Logo != null)
            {
                _logger.LogInformation("Using HIGH error correction level for logo QR code");
                return QRCodeGenerator.ECCLevel.H; // 30% correção
            }

            // Para velocidade, usar correção baixa apenas se especificado
            if (request.OptimizeForSpeed)
            {
                return QRCodeGenerator.ECCLevel.L; // 7% correção
            }

            // Padrão: correção média
            return QRCodeGenerator.ECCLevel.M; // 15% correção
        }

        // CORREÇÃO 8: Método de validação e processamento de logo aprimorado
        private bool ValidateLogoForQR(byte[] logoBytes, out string errorMessage)
        {
            errorMessage = "";
            
            if (logoBytes == null || logoBytes.Length == 0)
            {
                errorMessage = _localizer["LogoNotProvided"];
                return false;
            }

            // Validar tamanho máximo
            if (logoBytes.Length > 2 * 1024 * 1024) // 2MB
            {
                errorMessage = _localizer["LogoTooLarge"];
                return false;
            }

            try
            {
                using var stream = new MemoryStream(logoBytes);
                using var image = Image.Load(stream);
                
                // Validar dimensões mínimas
                if (image.Width < 32 || image.Height < 32)
                {
                    errorMessage = _localizer["LogoTooSmall"];
                    return false;
                }

                // Log das dimensões originais
                _logger.LogInformation("Logo original dimensions: {Width}x{Height} pixels", image.Width, image.Height);

                return true;
            }
            catch (Exception ex)
            {
                errorMessage = _localizer["InvalidImageFormat"];
                _logger.LogError(ex, "Error validating logo format");
                return false;
            }
        }

        // NOVO MÉTODO: Preprocessar logo para otimizar tamanho
        private byte[] PreprocessLogo(byte[] originalLogoBytes)
        {
            try
            {
                using var stream = new MemoryStream(originalLogoBytes);
                using var image = Image.Load(stream);
                
                // Se a largura for maior que 400px, redimensionar proporcionalmente
                if (image.Width > 400)
                {
                    var aspectRatio = (double)image.Height / image.Width;
                    var newWidth = 400;
                    var newHeight = (int)(newWidth * aspectRatio);
                    
                    _logger.LogInformation("Redimensionando logo de {OriginalWidth}x{OriginalHeight} para {NewWidth}x{NewHeight}", 
                        image.Width, image.Height, newWidth, newHeight);
                    
                    using var resizedImage = image.Clone(ctx => 
                        ctx.Resize(new ResizeOptions
                        {
                            Size = new Size(newWidth, newHeight),
                            Mode = ResizeMode.Stretch,
                            Sampler = KnownResamplers.Lanczos3 // Alta qualidade
                        }));
                    
                    using var outputStream = new MemoryStream();
                    // Preservar formato e cores originais ao redimensionar
                    resizedImage.Save(outputStream, new PngEncoder
                    {
                        ColorType = PngColorType.RgbWithAlpha,
                        CompressionLevel = PngCompressionLevel.DefaultCompression
                    });
                    var resizedBytes = outputStream.ToArray();
                    
                    _logger.LogInformation("Logo redimensionado: {OriginalSize} -> {NewSize} bytes", 
                        originalLogoBytes.Length, resizedBytes.Length);
                    
                    return resizedBytes;
                }
                
                _logger.LogDebug("Logo não precisa ser redimensionado: {Width}x{Height}", image.Width, image.Height);
                return originalLogoBytes;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao preprocessar logo, usando original");
                return originalLogoBytes;
            }
        }

        private int GetOptimalPixelsPerModule(int targetSize)
        {
            // Optimized algorithm for best quality/speed ratio
            return targetSize switch
            {
                <= 200 => 8,
                <= 300 => 12,
                <= 500 => 16,
                <= 800 => 20,
                _ => 24
            };
        }

        private string GenerateCacheKey(QRGenerationRequest request)
        {
            // CORREÇÃO DE CACHE: Incluir parâmetros de logo na chave de cache
            var logoHash = "";
            if (request.HasLogo && request.Logo != null && request.Logo.Length > 0)
            {
                // Usar logo processado (redimensionado se necessário) para o hash do cache
                var processedLogo = PreprocessLogo(request.Logo);
                using var logoSha = SHA256.Create();
                var logoHashBytes = logoSha.ComputeHash(processedLogo);
                logoHash = Convert.ToBase64String(logoHashBytes)[..16]; // Mais chars para evitar colisões
                _logger.LogDebug("Logo hash generated: {LogoHash} for processed logo size: {LogoSize} bytes", logoHash, processedLogo.Length);
            }
            else
            {
                logoHash = "no_logo";
                _logger.LogDebug("Using 'no_logo' hash for request without logo");
            }
            
            var fmt = (request.OutputFormat ?? "png").ToLowerInvariant();
            var keyData = $"{request.Content}|{request.Type}|{request.Size}|{request.PrimaryColor}|{request.BackgroundColor}|{request.QuickStyle}|{request.CornerStyle}|{request.Margin}|{request.HasLogo}|{logoHash}|{request.LogoSizePercent ?? 20}|{request.ApplyLogoColorization}|{fmt}";
            
            using var sha256 = SHA256.Create();
            var hash = sha256.ComputeHash(Encoding.UTF8.GetBytes(keyData));
            var cacheKey = $"qr_rapid_{Convert.ToBase64String(hash)[..16]}";
            
            _logger.LogDebug("Generated cache key: {CacheKey} for content: {Content}", cacheKey, request.Content[..Math.Min(20, request.Content.Length)]);
            return cacheKey;
        }

        private async Task<byte[]> ConvertPngBytesToWebPAsync(byte[] pngBytes)
        {
            return await Task.Run(() =>
            {
                using var image = Image.Load(pngBytes);
                using var ms = new MemoryStream();
                image.SaveAsWebp(ms, new WebpEncoder { Quality = 85 });
                return ms.ToArray();
            });
        }

        public async Task<byte[]> ConvertToSvgAsync(string qrCodeBase64)
        {
            return await Task.Run(() =>
            {
                // Convert PNG to SVG (simplified implementation)
                var svgContent = $@"<?xml version=""1.0"" encoding=""UTF-8""?>
<svg xmlns=""http://www.w3.org/2000/svg"" viewBox=""0 0 300 300"">
    <rect width=""300"" height=""300"" fill=""white""/>
    <image href=""data:image/png;base64,{qrCodeBase64}"" width=""300"" height=""300""/>
</svg>";
                return Encoding.UTF8.GetBytes(svgContent);
            });
        }

        public async Task<byte[]> ConvertToPdfAsync(string qrCodeBase64, int size = 300)
        {
            return await Task.Run(() =>
            {
                // Simplified PDF generation - in real implementation, use iTextSharp or similar
                var pdfHeader = "%PDF-1.4\n";
                var pdfBody = $"1 0 obj<</Type/Catalog/Pages 2 0 R>>endobj\n" +
                             $"2 0 obj<</Type/Pages/Kids[3 0 R]/Count 1>>endobj\n" +
                             $"3 0 obj<</Type/Page/Parent 2 0 R/MediaBox[0 0 {size} {size}]>>endobj\n" +
                             $"xref\n0 4\n0000000000 65535 f \n0000000010 00000 n \n0000000053 00000 n \n0000000125 00000 n \n";
                
                var pdfContent = pdfBody + $"trailer<</Size 4/Root 1 0 R>>\nstartxref\n{pdfHeader.Length + pdfBody.Length}\n%%EOF";

                return Encoding.UTF8.GetBytes(pdfHeader + pdfContent);
            });
        }

        public async Task<string> GenerateDynamicQRAsync(QRGenerationRequest request, string userId)
        {
            // For premium users only - dynamic QR codes that can be edited
            var dynamicId = Guid.NewGuid().ToString();
            var dynamicUrl = $"https://qrrapido.site/d/{dynamicId}";

            // Store mapping in cache/database
            var cacheKey = $"dynamic_qr_{dynamicId}";
            await _cache.SetStringAsync(cacheKey, request.Content, new DistributedCacheEntryOptions
            {
                SlidingExpiration = TimeSpan.FromDays(365) // Long-lived for premium users
            });

            return dynamicId;
        }

        public async Task<bool> UpdateDynamicQRAsync(string qrId, string newContent)
        {
            try
            {
                var cacheKey = $"dynamic_qr_{qrId}";
                await _cache.SetStringAsync(cacheKey, newContent, new DistributedCacheEntryOptions
                {
                    SlidingExpiration = TimeSpan.FromDays(365)
                });
                return true;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, $"Failed to update dynamic QR {qrId}: {ex.Message}");
                return false;
            }
        }

        private Color ParseHtmlColor(string htmlColor)
        {
            if (string.IsNullOrEmpty(htmlColor) || !htmlColor.StartsWith("#"))
            {
                return Color.Black;
            }

            try
            {
                if (htmlColor.Length == 7) // #RRGGBB
                {
                    var r = Convert.ToByte(htmlColor.Substring(1, 2), 16);
                    var g = Convert.ToByte(htmlColor.Substring(3, 2), 16);
                    var b = Convert.ToByte(htmlColor.Substring(5, 2), 16);
                    return Color.FromRgb(r, g, b);
                }
                else if (htmlColor.Length == 4) // #RGB
                {
                    var r = Convert.ToByte(htmlColor.Substring(1, 1) + htmlColor.Substring(1, 1), 16);
                    var g = Convert.ToByte(htmlColor.Substring(2, 1) + htmlColor.Substring(2, 1), 16);
                    var b = Convert.ToByte(htmlColor.Substring(3, 1) + htmlColor.Substring(3, 1), 16);
                    return Color.FromRgb(r, g, b);
                }
            }
            catch
            {
                return Color.Black;
            }

            return Color.Black;
        }

        private byte[] ColorToBytes(Color color)
        {
            var rgba = color.ToPixel<Rgba32>();
            return new byte[] { rgba.R, rgba.G, rgba.B };
        }

        // CORREÇÃO 7: Método ApplyLogoOverlay aprimorado com configurações avançadas
        private byte[] ApplyLogoOverlayEnhanced(byte[] qrBytes, byte[] logoBytes, QRGenerationRequest request)
        {
            _logger.LogDebug("Starting logo overlay - QR size: {QRSize} bytes, Logo size: {LogoSize} bytes", 
                qrBytes.Length, logoBytes.Length);
            try
            {
                using var qrStream = new MemoryStream(qrBytes);
                using var logoStream = new MemoryStream(logoBytes);
                
                _logger.LogDebug("Creating QR image from stream");
                using var qrImage = Image.Load(qrStream);
                
                _logger.LogDebug("Creating logo image from stream - QR dimensions: {QRWidth}x{QRHeight}", 
                    qrImage.Width, qrImage.Height);
                
                // CORREÇÃO: Validar stream do logo antes de criar image
                if (logoStream.Length == 0)
                {
                    _logger.LogError("Logo stream is empty - Size: {StreamLength} bytes", logoStream.Length);
                    return qrBytes;
                }
                
                logoStream.Position = 0; // Reset stream position
                using var logoImage = Image.Load(logoStream);
                
                _logger.LogDebug("Logo image created successfully - Logo dimensions: {LogoWidth}x{LogoHeight}", 
                    logoImage.Width, logoImage.Height);
                
                // CORREÇÃO: Validar dimensões do logo (muito grande pode causar problemas)
                if (logoImage.Width > 2000 || logoImage.Height > 2000)
                {
                    _logger.LogWarning("Logo image is very large - {LogoWidth}x{LogoHeight} pixels. This may cause processing issues.", 
                        logoImage.Width, logoImage.Height);
                }
                
                // CORREÇÃO: Validar se QR é muito pequeno para receber logo
                if (qrImage.Width < 50 || qrImage.Height < 50)
                {
                    _logger.LogWarning("QR image is very small - {QRWidth}x{QRHeight} pixels. Logo may not be visible.", 
                        qrImage.Width, qrImage.Height);
                }
                
                _logger.LogDebug("Creating final image with logo overlay");
                
                // MELHORIA: Tamanho configurável do logo (10-25%)
                var logoSizePercent = request.LogoSizePercent ?? 20;
                if (logoSizePercent > 25) logoSizePercent = 25; // Limite de segurança
                if (logoSizePercent < 10) logoSizePercent = 10; // Mínimo visível
                
                var logoSize = Math.Min(qrImage.Width, qrImage.Height) * logoSizePercent / 100;
                
                // Calculate center position
                var logoX = (qrImage.Width - logoSize) / 2;
                var logoY = (qrImage.Height - logoSize) / 2;
                
                // Create a white background circle for better contrast
                var backgroundSize = logoSize + 10; // Borda maior para melhor contraste
                var backgroundX = (qrImage.Width - backgroundSize) / 2;
                var backgroundY = (qrImage.Height - backgroundSize) / 2;
                
                // MELHORIA: Aplicar colorização se solicitado
                _logger.LogInformation("🎨 [LOGO DEBUG] Processing logo - ApplyColorization: {ApplyColorization}, PrimaryColor: {PrimaryColor}", 
                    request.ApplyLogoColorization, request.PrimaryColor);
                
                using Image finalLogo = request.ApplyLogoColorization
                    ? ApplyLogoColorization(logoImage, request.PrimaryColor)
                    : logoImage.Clone(ctx => { }); // Create a copy to avoid disposing the original
                
                _logger.LogInformation("🎨 [LOGO DEBUG] Logo processing path: {Path}", 
                    request.ApplyLogoColorization ? "COLORIZED" : "ORIGINAL_COLORS");
                
                if (finalLogo == null)
                {
                    _logger.LogError("Final logo is null after processing, cannot apply logo overlay");
                    return qrBytes; // Return original QR if logo processing fails
                }
                
                _logger.LogDebug("Drawing logo at position ({LogoX}, {LogoY}) with size {LogoSize}", 
                    logoX, logoY, logoSize);
                
                // Clone the QR image and apply logo overlay
                using var finalImage = qrImage.Clone(ctx =>
                {
                    // Fill white background circle for logo
                    var center = new PointF(backgroundX + backgroundSize / 2f, backgroundY + backgroundSize / 2f);
                    var radius = backgroundSize / 2f;
                    ctx.Fill(Color.White, new SixLabors.ImageSharp.Drawing.EllipsePolygon(center, radius));
                    
                    // Resize logo to fit
                    using var resizedLogo = finalLogo.Clone(logoCtx => 
                        logoCtx.Resize(new ResizeOptions
                        {
                            Size = new Size(logoSize, logoSize),
                            Mode = ResizeMode.Stretch,
                            Sampler = KnownResamplers.Lanczos3
                        }));
                    
                    // Draw the logo
                    ctx.DrawImage(resizedLogo, new Point(logoX, logoY), 1.0f);
                });
                
                // Convert back to byte array
                _logger.LogDebug("Saving final image with logo overlay");
                using var outputStream = new MemoryStream();
                finalImage.Save(outputStream, new PngEncoder
                {
                    ColorType = PngColorType.RgbWithAlpha,
                    CompressionLevel = PngCompressionLevel.DefaultCompression
                });
                var result = outputStream.ToArray();
                
                _logger.LogInformation("Logo overlay completed successfully - Final image size: {FinalSize} bytes", 
                    result.Length);
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error applying enhanced logo overlay - QR: {QRSize}bytes, Logo: {LogoSize}bytes, Error: {ErrorMessage}", 
                    qrBytes.Length, logoBytes.Length, ex.Message);
                _logger.LogError("Stack trace: {StackTrace}", ex.StackTrace);
                // Return original QR code if logo overlay fails
                return qrBytes;
            }
        }

        // CORREÇÃO 9: Método para colorização do logo
        private Image ApplyLogoColorization(Image originalLogo, string targetColor)
        {
            _logger.LogDebug("Starting logo colorization - Original size: {Width}x{Height}, Target color: {Color}", 
                originalLogo.Width, originalLogo.Height, targetColor);
            try
            {
                var color = ParseHtmlColor(targetColor);
                var rgba = color.ToPixel<Rgba32>();
                _logger.LogDebug("Parsed color: R={R}, G={G}, B={B}", rgba.R, rgba.G, rgba.B);
                
                // CORREÇÃO: Verificar se as dimensões são válidas para colorização
                if (originalLogo.Width <= 0 || originalLogo.Height <= 0)
                {
                    _logger.LogError("Invalid logo dimensions for colorization - {Width}x{Height}", 
                        originalLogo.Width, originalLogo.Height);
                    return originalLogo.Clone(ctx => { });
                }
                
                _logger.LogDebug("Creating colorized image with dimensions {Width}x{Height}", 
                    originalLogo.Width, originalLogo.Height);
                
                // Apply intelligent colorization: preserve light backgrounds, colorize dark elements
                var colorizedLogo = originalLogo.Clone(ctx =>
                {
                    ctx.ProcessPixelRowsAsVector4((span, point) =>
                    {
                        for (int x = 0; x < span.Length; x++)
                        {
                            var pixel = span[x];
                            
                            // Calculate luminance (brightness) of the pixel
                            var luminance = (pixel.X * 0.299f + pixel.Y * 0.587f + pixel.Z * 0.114f);
                            
                            // Define threshold for "background" vs "content"
                            // Values above 0.8 (bright) are considered background and preserved
                            var brightnessThreshold = 0.8f;
                            
                            if (luminance > brightnessThreshold)
                            {
                                // Preserve bright pixels (background) - keep original colors
                                span[x] = pixel;
                            }
                            else
                            {
                                // Colorize dark pixels (content/drawings) with QR color
                                // Use inverse luminance for intensity (darker pixels get more color)
                                var intensity = Math.Max(0.1f, 1.0f - luminance);
                                span[x] = new Vector4(
                                    rgba.R / 255f * intensity,
                                    rgba.G / 255f * intensity,
                                    rgba.B / 255f * intensity,
                                    pixel.W  // Preserve alpha
                                );
                            }
                        }
                    });
                });
                
                _logger.LogInformation("✨ Smart logo colorization completed - Preserving bright pixels (>0.8), colorizing dark content with {Color}", targetColor);
                return colorizedLogo;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error applying logo colorization - Size: {Width}x{Height}, Color: {Color}, Error: {ErrorMessage}", 
                    originalLogo.Width, originalLogo.Height, targetColor, ex.Message);
                return originalLogo.Clone(ctx => { }); // Return a copy if error occurs
            }
        }

        private byte[] ApplyCornerStyle(byte[] qrBytes, string cornerStyle, int targetSize)
        {
            if (cornerStyle == "square" || string.IsNullOrEmpty(cornerStyle))
            {
                return qrBytes; // No processing needed for square style
            }

            try
            {
                _logger.LogInformation("Applying corner style '{CornerStyle}' to QR code", cornerStyle);

                using var qrImage = Image.Load<Rgba32>(qrBytes);
                int width = qrImage.Width;
                int height = qrImage.Height;

                // Detect module size by scanning the image
                int moduleSize = DetectModuleSize(qrImage);
                if (moduleSize <= 0)
                {
                    _logger.LogWarning("Could not detect module size, returning original QR code");
                    return qrBytes;
                }

                _logger.LogDebug("Detected module size: {ModuleSize}px for {Width}x{Height} QR code", moduleSize, width, height);

                // Create a new image with styled modules
                using var styledImage = new Image<Rgba32>(width, height);

                // Process each module
                for (int y = 0; y < height; y += moduleSize)
                {
                    for (int x = 0; x < width; x += moduleSize)
                    {
                        // Check if this module is dark (part of the QR pattern)
                        var centerPixel = qrImage[x + moduleSize / 2, y + moduleSize / 2];
                        bool isDark = centerPixel.R < 128; // Dark if RGB < 128

                        if (isDark)
                        {
                            // Draw styled module based on cornerStyle
                            DrawStyledModule(styledImage, x, y, moduleSize, cornerStyle, centerPixel);
                        }
                        else
                        {
                            // Draw background (light modules)
                            DrawRectangle(styledImage, x, y, moduleSize, moduleSize, centerPixel);
                        }
                    }
                }

                // Convert back to bytes
                using var outputStream = new MemoryStream();
                styledImage.SaveAsPng(outputStream);
                _logger.LogInformation("Successfully applied corner style '{CornerStyle}'", cornerStyle);
                return outputStream.ToArray();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error applying corner style {CornerStyle}, returning original QR code", cornerStyle);
                return qrBytes;
            }
        }

        private int DetectModuleSize(Image<Rgba32> qrImage)
        {
            // Scan horizontally from left to find the first transition from light to dark
            int width = qrImage.Width;
            int height = qrImage.Height;
            int midY = height / 2;

            bool wasLight = true;
            int darkStart = -1;
            int darkEnd = -1;

            for (int x = 0; x < width; x++)
            {
                var pixel = qrImage[x, midY];
                bool isLight = pixel.R >= 128;

                if (wasLight && !isLight)
                {
                    // Transition from light to dark
                    darkStart = x;
                }
                else if (!wasLight && isLight && darkStart >= 0)
                {
                    // Transition from dark to light
                    darkEnd = x;
                    break;
                }

                wasLight = isLight;
            }

            if (darkStart >= 0 && darkEnd > darkStart)
            {
                return darkEnd - darkStart;
            }

            // Fallback: estimate based on typical QR code structure (21-177 modules)
            // Most common is 25-29 modules for QR version 1-5
            return width / 25; // Rough estimate
        }

        private void DrawStyledModule(Image<Rgba32> image, int x, int y, int size, string style, Rgba32 color)
        {
            switch (style.ToLower())
            {
                case "rounded":
                    DrawRoundedRectangle(image, x, y, size, size, size / 4, color);
                    break;
                case "circle":
                    DrawCircle(image, x + size / 2, y + size / 2, size / 2, color);
                    break;
                default:
                    DrawRectangle(image, x, y, size, size, color);
                    break;
            }
        }

        private void DrawRectangle(Image<Rgba32> image, int x, int y, int width, int height, Rgba32 color)
        {
            for (int dy = 0; dy < height; dy++)
            {
                for (int dx = 0; dx < width; dx++)
                {
                    int px = x + dx;
                    int py = y + dy;
                    if (px >= 0 && px < image.Width && py >= 0 && py < image.Height)
                    {
                        image[px, py] = color;
                    }
                }
            }
        }

        private void DrawRoundedRectangle(Image<Rgba32> image, int x, int y, int width, int height, int radius, Rgba32 color)
        {
            for (int dy = 0; dy < height; dy++)
            {
                for (int dx = 0; dx < width; dx++)
                {
                    int px = x + dx;
                    int py = y + dy;

                    if (px < 0 || px >= image.Width || py < 0 || py >= image.Height)
                        continue;

                    // Check if pixel is inside rounded rectangle
                    bool inCorner = false;
                    int distX = 0, distY = 0;

                    // Top-left corner
                    if (dx < radius && dy < radius)
                    {
                        distX = radius - dx;
                        distY = radius - dy;
                        inCorner = true;
                    }
                    // Top-right corner
                    else if (dx >= width - radius && dy < radius)
                    {
                        distX = dx - (width - radius - 1);
                        distY = radius - dy;
                        inCorner = true;
                    }
                    // Bottom-left corner
                    else if (dx < radius && dy >= height - radius)
                    {
                        distX = radius - dx;
                        distY = dy - (height - radius - 1);
                        inCorner = true;
                    }
                    // Bottom-right corner
                    else if (dx >= width - radius && dy >= height - radius)
                    {
                        distX = dx - (width - radius - 1);
                        distY = dy - (height - radius - 1);
                        inCorner = true;
                    }

                    if (inCorner)
                    {
                        // Check if point is inside the rounded corner
                        double distance = Math.Sqrt(distX * distX + distY * distY);
                        if (distance <= radius)
                        {
                            image[px, py] = color;
                        }
                    }
                    else
                    {
                        // Inside the main rectangle (not in corners)
                        image[px, py] = color;
                    }
                }
            }
        }

        private void DrawCircle(Image<Rgba32> image, int centerX, int centerY, int radius, Rgba32 color)
        {
            int x0 = centerX - radius;
            int y0 = centerY - radius;
            int diameter = radius * 2;

            for (int dy = 0; dy <= diameter; dy++)
            {
                for (int dx = 0; dx <= diameter; dx++)
                {
                    int px = x0 + dx;
                    int py = y0 + dy;

                    if (px < 0 || px >= image.Width || py < 0 || py >= image.Height)
                        continue;

                    // Calculate distance from center
                    double distance = Math.Sqrt(Math.Pow(dx - radius, 2) + Math.Pow(dy - radius, 2));

                    if (distance <= radius)
                    {
                        image[px, py] = color;
                    }
                }
            }
        }

        // QRModule class removed - was only used for corner styling which is temporarily simplified
    }
}