using Microsoft.Extensions.Localization;
using QRRapidoApp.Models;
using QRRapidoApp.Models.ViewModels;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.PixelFormats;
using System.Collections.Generic;

namespace QRRapidoApp.Services
{
    public class LogoReadabilityAnalyzer
    {
        private readonly ILogger<LogoReadabilityAnalyzer> _logger;
        private readonly IStringLocalizer<LogoReadabilityAnalyzer> _localizer;

        public LogoReadabilityAnalyzer(ILogger<LogoReadabilityAnalyzer> logger, IStringLocalizer<LogoReadabilityAnalyzer> localizer)
        {
            _logger = logger;
            _localizer = localizer;
        }

        public async Task<LogoReadabilityInfo> AnalyzeAsync(QRGenerationRequest request, int qrSize = 300)
        {
            var result = new LogoReadabilityInfo();

            if (!request.HasLogo || request.Logo == null || request.Logo.Length == 0)
            {
                result.HasLogo = false;
                result.ReadabilityScore = 100;
                result.DifficultyLevel = ReadabilityLevel.VeryEasy.ToString();
                result.UserMessage = "✅ Perfeita legibilidade! QR code sem logo é sempre facilmente lido.";
                return result;
            }

            try
            {
                result.HasLogo = true;
                result.LogoComplexity = await AnalyzeLogoComplexityAsync(request.Logo);
                result.LogoSizePercent = request.LogoSizePercent ?? 20;

                // Calcular score baseado em múltiplos fatores
                result.ReadabilityScore = CalculateReadabilityScore(result.LogoComplexity, result.LogoSizePercent, qrSize);
                result.DifficultyLevel = GetDifficultyLevel(result.ReadabilityScore).ToString();
                result.UserMessage = GenerateUserMessage(result.ReadabilityScore, result.LogoSizePercent);
                result.Tips = GeneratePersonalizedTips(result.LogoComplexity, result.LogoSizePercent, result.ReadabilityScore);

                _logger.LogInformation("Logo readability analysis completed - Score: {Score}, Size: {Size}%, Level: {Level}", 
                    result.ReadabilityScore, result.LogoSizePercent, result.DifficultyLevel);

                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error analyzing logo readability");
                
                // Fallback para análise básica baseada apenas no tamanho
                result.HasLogo = true;
                result.LogoSizePercent = request.LogoSizePercent ?? 20;
                result.ReadabilityScore = Math.Max(40, 100 - (result.LogoSizePercent - 15) * 3);
                result.DifficultyLevel = GetDifficultyLevel(result.ReadabilityScore).ToString();
                result.UserMessage = GenerateUserMessage(result.ReadabilityScore, result.LogoSizePercent);
                result.Tips = new List<string> { "⚠️ Análise limitada devido a erro técnico. Teste sempre em vários dispositivos." };

                return result;
            }
        }

        private async Task<LogoComplexity> AnalyzeLogoComplexityAsync(byte[] logoBytes)
        {
            return await Task.Run(() =>
            {
                try
                {
                    using var stream = new MemoryStream(logoBytes);
                    using var image = Image.Load<Rgba32>(stream);

                    var complexity = new LogoComplexity
                    {
                        Width = image.Width,
                        Height = image.Height,
                        IsSquare = Math.Abs(image.Width - image.Height) <= Math.Min(image.Width, image.Height) * 0.1,
                        FileSizeBytes = logoBytes.Length,
                        FileFormat = DetectImageFormat(logoBytes)
                    };

                    // Analisar transparência
                    complexity.HasTransparency = HasTransparency(image);

                    // Analisar complexidade de cores
                    var colorAnalysis = AnalyzeColors(image);
                    complexity.DominantColorCount = colorAnalysis.dominantColors;
                    complexity.ContrastRatio = colorAnalysis.contrastRatio;

                    _logger.LogDebug("Logo complexity analysis - {Width}x{Height}, Square: {IsSquare}, Transparency: {HasTransparency}, Colors: {Colors}", 
                        complexity.Width, complexity.Height, complexity.IsSquare, complexity.HasTransparency, complexity.DominantColorCount);

                    return complexity;
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "Error analyzing logo complexity");
                    return new LogoComplexity
                    {
                        Width = 100,
                        Height = 100,
                        IsSquare = true,
                        HasTransparency = false,
                        DominantColorCount = 5,
                        ContrastRatio = 0.5,
                        FileFormat = "unknown",
                        FileSizeBytes = logoBytes.Length
                    };
                }
            });
        }

        private int CalculateReadabilityScore(LogoComplexity complexity, int logoSizePercent, int qrSize)
        {
            int score = 100; // Base score

            // Penalização por tamanho (fator mais importante)
            if (logoSizePercent > 20)
            {
                score -= (logoSizePercent - 20) * 2; // -2 pontos por % acima de 20%
            }

            // Penalização por complexidade de cores
            if (complexity.DominantColorCount > 5)
            {
                score -= (complexity.DominantColorCount - 5) * 3; // -3 pontos por cor extra
            }

            // Penalização por baixo contraste
            if (complexity.ContrastRatio < 0.3)
            {
                score -= 10; // Contraste muito baixo
            }

            // Bonificações
            if (complexity.HasTransparency)
            {
                score += 5; // PNG com transparência é melhor
            }

            if (complexity.IsSquare)
            {
                score += 5; // Logo quadrado funciona melhor
            }

            if (qrSize >= 500)
            {
                score += 5; // QR codes maiores facilitam leitura
            }

            // Penalização por logo muito grande em pixels (pode ser mais difícil de processar)
            if (complexity.Width > 800 || complexity.Height > 800)
            {
                score -= 5;
            }

            // Garantir que o score fique entre 0-100
            return Math.Max(0, Math.Min(100, score));
        }

        private ReadabilityLevel GetDifficultyLevel(int score)
        {
            return score switch
            {
                >= 85 => ReadabilityLevel.VeryEasy,
                >= 70 => ReadabilityLevel.Easy,
                >= 55 => ReadabilityLevel.Medium,
                >= 40 => ReadabilityLevel.Hard,
                _ => ReadabilityLevel.VeryHard
            };
        }

        private string GenerateUserMessage(int score, int logoSizePercent)
        {
            return score switch
            {
                >= 85 => $"✅ Excelente legibilidade! Logo de {logoSizePercent}% será facilmente lido por qualquer celular.",
                >= 70 => $"🟢 Boa legibilidade! Logo de {logoSizePercent}% deve funcionar bem na maioria dos dispositivos.",
                >= 55 => $"⚠️ Legibilidade moderada. Logo de {logoSizePercent}% pode exigir melhor iluminação ou posicionamento.",
                >= 40 => $"🟡 Legibilidade baixa. Logo de {logoSizePercent}% pode ser difícil de ler. Considere reduzir para melhor resultado.",
                _ => $"🔴 Legibilidade muito baixa. Logo de {logoSizePercent}% provavelmente será difícil de escanear. Recomendamos reduzir significativamente."
            };
        }

        private List<string> GeneratePersonalizedTips(LogoComplexity complexity, int logoSizePercent, int score)
        {
            var tips = new List<string>();

            // Dicas básicas sempre presentes
            tips.Add("📱 Teste sempre em vários apps de QR Code diferentes");

            // Dicas baseadas no score
            if (score < 70)
            {
                tips.Add("💡 Use boa iluminação ao escanear para melhor resultado");
            }

            // Dicas baseadas no tamanho
            if (logoSizePercent > 22)
            {
                tips.Add($"📏 Considere reduzir logo para 18-20% (atual: {logoSizePercent}%)");
            }

            // Dicas baseadas na complexidade
            if (!complexity.HasTransparency)
            {
                tips.Add("🎨 PNG com fundo transparente melhora a legibilidade");
            }

            if (!complexity.IsSquare)
            {
                tips.Add("🔲 Logos quadrados funcionam melhor que retangulares");
            }

            if (complexity.DominantColorCount > 6)
            {
                tips.Add("🌈 Logos com menos cores (2-4) são mais fáceis de ler");
            }

            if (complexity.ContrastRatio < 0.4)
            {
                tips.Add("⚡ Aumente o contraste do logo para melhor visibilidade");
            }

            // Dica sobre tamanho do QR
            tips.Add("📐 QR Codes maiores (500px+) facilitam leitura com logo");

            // Dica final baseada no nível de dificuldade
            if (score < 55)
            {
                tips.Add("🔧 Para máxima compatibilidade, considere versão sem logo para impressões pequenas");
            }

            return tips;
        }

        private bool HasTransparency(Image<Rgba32> image)
        {
            try
            {
                // Verificar se há pixels com alpha < 255 (transparência)
                var hasTransparency = false;
                image.ProcessPixelRows(accessor =>
                {
                    for (int y = 0; y < accessor.Height && !hasTransparency; y++)
                    {
                        var pixelRow = accessor.GetRowSpan(y);
                        for (int x = 0; x < pixelRow.Length && !hasTransparency; x++)
                        {
                            if (pixelRow[x].A < 255)
                            {
                                hasTransparency = true;
                            }
                        }
                    }
                });

                return hasTransparency;
            }
            catch
            {
                return false; // Assume não transparente se der erro
            }
        }

        private (int dominantColors, double contrastRatio) AnalyzeColors(Image<Rgba32> image)
        {
            try
            {
                var colorCounts = new Dictionary<uint, int>();
                var totalPixels = 0;
                var brightPixels = 0;

                // Amostragem para performance (analisa a cada 4 pixels)
                image.ProcessPixelRows(accessor =>
                {
                    for (int y = 0; y < accessor.Height; y += 4)
                    {
                        var pixelRow = accessor.GetRowSpan(y);
                        for (int x = 0; x < pixelRow.Length; x += 4)
                        {
                            var pixel = pixelRow[x];
                            
                            // Ignorar pixels totalmente transparentes
                            if (pixel.A < 128) continue;

                            // Quantizar cores para reduzir variações
                            var quantizedColor = QuantizeColor(pixel);
                            colorCounts[quantizedColor] = colorCounts.GetValueOrDefault(quantizedColor, 0) + 1;

                            // Calcular brilho para contraste
                            var luminance = (pixel.R * 0.299 + pixel.G * 0.587 + pixel.B * 0.114) / 255.0;
                            if (luminance > 0.5) brightPixels++;
                            totalPixels++;
                        }
                    }
                });

                var dominantColors = Math.Min(colorCounts.Count, 10); // Limitar a 10 cores dominantes
                var contrastRatio = totalPixels > 0 ? (double)brightPixels / totalPixels : 0.5;

                return (dominantColors, contrastRatio);
            }
            catch
            {
                return (5, 0.5); // Valores padrão em caso de erro
            }
        }

        private uint QuantizeColor(Rgba32 color)
        {
            // Quantizar cores para 32 níveis (reduz variações mínimas)
            var r = (byte)((color.R / 8) * 8);
            var g = (byte)((color.G / 8) * 8);
            var b = (byte)((color.B / 8) * 8);
            
            return (uint)(r << 16 | g << 8 | b);
        }

        private string DetectImageFormat(byte[] imageBytes)
        {
            if (imageBytes.Length < 4) return "unknown";

            // PNG signature
            if (imageBytes[0] == 0x89 && imageBytes[1] == 0x50 && imageBytes[2] == 0x4E && imageBytes[3] == 0x47)
                return "PNG";

            // JPEG signature
            if (imageBytes[0] == 0xFF && imageBytes[1] == 0xD8)
                return "JPEG";

            // GIF signature
            if (imageBytes[0] == 0x47 && imageBytes[1] == 0x49 && imageBytes[2] == 0x46)
                return "GIF";

            // WebP signature
            if (imageBytes.Length > 12 && 
                imageBytes[0] == 0x52 && imageBytes[1] == 0x49 && imageBytes[2] == 0x46 && imageBytes[3] == 0x46 &&
                imageBytes[8] == 0x57 && imageBytes[9] == 0x45 && imageBytes[10] == 0x42 && imageBytes[11] == 0x50)
                return "WebP";

            return "unknown";
        }
    }
}