using Microsoft.Extensions.Caching.Memory;
using System.Text;
using System.Text.Json;
using System.Linq;
using OnlyOneAccessTemplate.Models;
using global::OnlyOneAccessTemplate.Models;

namespace OnlyOneAccessTemplate.Services
{

    public class SeoService : ISeoService
    {
        private readonly ISiteConfigurationService _siteConfig;
        private readonly ILanguageService _languageService;
        private readonly IMemoryCache _cache;
        private readonly IConfiguration _configuration;
        private readonly ILogger<SeoService> _logger;

        public SeoService(
            ISiteConfigurationService siteConfig,
            ILanguageService languageService,
            IMemoryCache cache,
            IConfiguration configuration,
            ILogger<SeoService> logger)
        {
            _siteConfig = siteConfig;
            _languageService = languageService;
            _cache = cache;
            _configuration = configuration;
            _logger = logger;
        }

        public async Task<SeoMetadata> GenerateSeoMetadataAsync(string language, string pageName, PageContent? content = null)
        {
            var cacheKey = $"seo_metadata_{language}_{pageName}";

            if (_cache.TryGetValue(cacheKey, out SeoMetadata? cachedMetadata) && cachedMetadata != null)
            {
                return cachedMetadata;
            }

            try
            {
                var configuration = await _siteConfig.GetConfigurationAsync(language);
                //content = content ?? await _siteConfig.ge.GetPageContentAsync(language, pageName);

                var baseUrl = _configuration.GetValue<string>("SEO:DefaultDomain") ?? "https://localhost";
                var canonicalUrl = BuildCanonicalUrl(baseUrl, language, pageName);
                var hreflangUrls = _languageService.GetHreflangUrls(canonicalUrl, language);

                var metadata = new SeoMetadata(
                    Title: content?.MetaTitle ?? content?.Title ?? configuration.SiteTitle,
                    Description: content?.Description ?? configuration.SiteDescription,
                    Keywords: content?.Keywords ?? configuration.SiteKeywords,
                    OgTitle: content?.Title ?? configuration.SiteTitle,
                    OgDescription: content?.Description ?? configuration.SiteDescription,
                    OgImage: content?.OgImage ?? configuration.OgImage,
                    CanonicalUrl: canonicalUrl,
                    HreflangUrls: hreflangUrls,
                    StructuredData: await GenerateStructuredDataAsync(language, "WebPage", new { content, configuration })
                );

                _cache.Set(cacheKey, metadata, TimeSpan.FromMinutes(15));
                return metadata;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao gerar metadata SEO para {Language}/{PageName}", language, pageName);
                return CreateFallbackMetadata(language, pageName);
            }
        }

        public async Task<string> GenerateStructuredDataAsync(string language, string pageType, object data)
        {
            try
            {
                var configuration = await _siteConfig.GetConfigurationAsync(language);
                var baseUrl = _configuration.GetValue<string>("SEO:DefaultDomain") ?? "https://localhost";

                var structuredData = pageType.ToLowerInvariant() switch
                {
                    "webpage" => GenerateWebPageStructuredData(configuration, baseUrl, language, data),
                    "organization" => GenerateOrganizationStructuredData(configuration, baseUrl),
                    "breadcrumb" => GenerateBreadcrumbStructuredData(baseUrl, language, data),
                    "faq" => GenerateFaqStructuredData(data),
                    "product" => GenerateProductStructuredData(configuration, data),
                    _ => GenerateWebPageStructuredData(configuration, baseUrl, language, data)
                };

                return JsonSerializer.Serialize(structuredData, new JsonSerializerOptions
                {
                    WriteIndented = false,
                    PropertyNamingPolicy = JsonNamingPolicy.CamelCase
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao gerar structured data para {PageType}", pageType);
                return "{}";
            }
        }

        public async Task<List<SeoIssue>> ValidateSeoAsync(string url)
        {
            var issues = new List<SeoIssue>();

            try
            {
                // Esta implementação seria expandida com validações reais
                // Por enquanto, retorna uma lista básica de verificações

                if (string.IsNullOrEmpty(url))
                {
                    issues.Add(new SeoIssue("URL", "URL não fornecida", "High", ""));
                }

                // Adicionar mais validações conforme necessário
                // - Verificar se title tem tamanho adequado
                // - Verificar se description tem tamanho adequado
                // - Verificar se há headings estruturados
                // - Verificar se há alt text nas imagens
                // - Verificar velocidade da página
                // - Verificar responsividade

                return issues;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao validar SEO para URL {Url}", url);
                issues.Add(new SeoIssue("Validation", "Erro na validação SEO", "High", ""));
                return issues;
            }
        }

        private object GenerateWebPageStructuredData(SiteConfiguration config, string baseUrl, string language, object data)
        {
            return new
            {
                Context = "https://schema.org",
                Type = "WebPage",
                Name = config.SiteTitle,
                Description = config.SiteDescription,
                Url = baseUrl,
                InLanguage = language,
                IsPartOf = new
                {
                    Type = "WebSite",
                    Name = config.SiteTitle,
                    Url = baseUrl
                },
                DatePublished = DateTime.UtcNow.ToString("yyyy-MM-dd"),
                DateModified = DateTime.UtcNow.ToString("yyyy-MM-dd")
            };
        }

        public async Task<SeoMetadata> GenerateMetadataForPageAsync(HttpContext context, string language, string pageName, PageContent? customContent = null)
        {
            var currentUrl = $"{context.Request.Scheme}://{context.Request.Host}{context.Request.Path}";
            return await GenerateSeoMetadataAsync(language, pageName, customContent);
        }

        public async Task<string> GenerateCanonicalUrlAsync(HttpContext context, string language, string pageName)
        {
            var baseUrl = $"{context.Request.Scheme}://{context.Request.Host}";
            return BuildCanonicalUrl(baseUrl, language, pageName);
        }

        public async Task<Dictionary<string, string>> GenerateMetaTagsAsync(SeoMetadata metadata)
        {
            return new Dictionary<string, string>
        {
            { "title", metadata.Title },
            { "description", metadata.Description },
            { "keywords", metadata.Keywords },
            { "canonical", metadata.CanonicalUrl },
            { "author", metadata.Author ?? "" }
        };
        }

        public async Task<string> GenerateOpenGraphTagsAsync(SeoMetadata metadata)
        {
            var tags = new StringBuilder();
            tags.AppendLine($"<meta property=\"og:title\" content=\"{metadata.OgTitle}\" />");
            tags.AppendLine($"<meta property=\"og:description\" content=\"{metadata.OgDescription}\" />");
            tags.AppendLine($"<meta property=\"og:image\" content=\"{metadata.OgImage}\" />");
            tags.AppendLine($"<meta property=\"og:url\" content=\"{metadata.CanonicalUrl}\" />");
            tags.AppendLine($"<meta property=\"og:type\" content=\"{metadata.OgType}\" />");
            return tags.ToString();
        }

        public async Task<string> GenerateTwitterCardTagsAsync(SeoMetadata metadata)
        {
            var tags = new StringBuilder();
            tags.AppendLine($"<meta name=\"twitter:card\" content=\"{metadata.TwitterCard}\" />");
            tags.AppendLine($"<meta name=\"twitter:title\" content=\"{metadata.OgTitle}\" />");
            tags.AppendLine($"<meta name=\"twitter:description\" content=\"{metadata.OgDescription}\" />");
            tags.AppendLine($"<meta name=\"twitter:image\" content=\"{metadata.OgImage}\" />");
            return tags.ToString();
        }

        public async Task<string> GenerateJsonLdAsync(string language, string pageType, object data)
        {
            return await GenerateStructuredDataAsync(language, pageType, data);
        }

        public bool ValidateMetadata(SeoMetadata metadata, out List<SeoIssue> issues)
        {
            issues = new List<SeoIssue>();

            if (string.IsNullOrEmpty(metadata.Title))
            {
                issues.Add(new SeoIssue("Title", "Título não pode estar vazio", "High", "title"));
            }
            else if (metadata.Title.Length > 60)
            {
                issues.Add(new SeoIssue("Title", "Título muito longo (máx. 60 caracteres)", "Medium", "title"));
            }

            if (string.IsNullOrEmpty(metadata.Description))
            {
                issues.Add(new SeoIssue("Description", "Descrição não pode estar vazia", "High", "meta[name='description']"));
            }
            else if (metadata.Description.Length > 160)
            {
                issues.Add(new SeoIssue("Description", "Descrição muito longa (máx. 160 caracteres)", "Medium", "meta[name='description']"));
            }

            if (string.IsNullOrEmpty(metadata.OgImage))
            {
                issues.Add(new SeoIssue("OpenGraph", "Imagem Open Graph não definida", "Medium", "meta[property='og:image']"));
            }

            return !issues.Any(i => i.Severity == "High");
        }

        private object GenerateOrganizationStructuredData(SiteConfiguration config, string baseUrl)
        {
            return new
            {
                Context = "https://schema.org",
                Type = "Organization",
                Name = config.SiteTitle,
                Url = baseUrl,
                Logo = new
                {
                    Type = "ImageObject",
                    Url = $"{baseUrl}/logo.png"
                },
                SameAs = new[]
                {
                "Facebook"
                }
            };
        }

        private object GenerateBreadcrumbStructuredData(string baseUrl, string language, object data)
        {
            return new
            {
                Context = "https://schema.org",
                Type = "BreadcrumbList",
                ItemListElement = new[]
                {
                new
                {
                    Type = "ListItem",
                    Position = 1,
                    Name = language switch
                    {
                        "en" => "Home",
                        "es" => "Inicio",
                        _ => "Início"
                    },
                    Item = baseUrl
                }
                // Adicionar mais items do breadcrumb conforme necessário
            }
            };
        }

        private object GenerateFaqStructuredData(object data)
        {
            return new
            {
                Context = "https://schema.org",
                Type = "FAQPage",
                MainEntity = new[]
                {
                // Exemplo de FAQ - expandir conforme necessário
                new
                {
                    Type = "Question",
                    Name = "Como funciona?",
                    AcceptedAnswer = new
                    {
                        Type = "Answer",
                        Text = "Explicação de como funciona..."
                    }
                }
            }
            };
        }

        private object GenerateProductStructuredData(SiteConfiguration config, object data)
        {
            return new
            {
                Context = "https://schema.org",
                Type = "Product",
                Name = "Nome do Produto",
                Description = "Descrição do produto",
                Brand = new
                {
                    Type = "Brand",
                    Name = config.SiteTitle
                },
                Offers = new
                {
                    Type = "Offer",
                    PriceCurrency = "BRL",
                    Price = "0",
                    Availability = "https://schema.org/InStock"
                }
            };
        }

        private string BuildCanonicalUrl(string baseUrl, string language, string pageName)
        {
            var url = baseUrl.TrimEnd('/');

            if (language != _languageService.GetDefaultLanguage())
            {
                url += $"/{language}";
            }

            if (!string.IsNullOrEmpty(pageName) && pageName != "index")
            {
                url += $"/{pageName}";
            }

            return url;
        }

        private SeoMetadata CreateFallbackMetadata(string language, string pageName)
        {
            var defaultTitle = language switch
            {
                "en" => "Page Not Found",
                "es" => "Página No Encontrada",
                _ => "Página Não Encontrada"
            };

            var defaultDescription = language switch
            {
                "en" => "The requested page could not be found.",
                "es" => "La página solicitada no pudo ser encontrada.",
                _ => "A página solicitada não pôde ser encontrada."
            };

            return new SeoMetadata(
                Title: defaultTitle,
                Description: defaultDescription,
                Keywords: "",
                OgTitle: defaultTitle,
                OgDescription: defaultDescription,
                OgImage: "",
                CanonicalUrl: "",
                HreflangUrls: new Dictionary<string, string>(),
                StructuredData: "{}"
            );
        }
    }
}