using Microsoft.Extensions.Caching.Memory;
using System.Globalization;

namespace OnlyOneAccessTemplate.Services
{
    public class LanguageService : ILanguageService
    {
        private readonly IMemoryCache _cache;
        private readonly ILogger<LanguageService> _logger;

        private static readonly Dictionary<string, string> SupportedLanguages = new()
    {
        { "pt", "Português" },
        { "en", "English" },
        { "es", "Español" }
    };

        private static readonly Dictionary<string, string> LanguageCultures = new()
    {
        { "pt", "pt-BR" },
        { "en", "en-US" },
        { "es", "es-ES" }
    };

        public LanguageService(IMemoryCache cache, ILogger<LanguageService> logger)
        {
            _cache = cache;
            _logger = logger;
        }

        public string GetCurrentLanguage(HttpContext context)
        {
            try
            {
                // 1. Verificar na URL
                var pathLanguage = GetLanguageFromPath(context.Request.Path);
                if (!string.IsNullOrEmpty(pathLanguage))
                {
                    return pathLanguage;
                }

                // 2. Verificar cookie de preferência
                if (context.Request.Cookies.TryGetValue("preferred_language", out var cookieLanguage) &&
                    SupportedLanguages.ContainsKey(cookieLanguage))
                {
                    return cookieLanguage;
                }

                // 3. Verificar Accept-Language header
                var browserLanguage = GetLanguageFromBrowser(context);
                if (!string.IsNullOrEmpty(browserLanguage))
                {
                    return browserLanguage;
                }

                // 4. Retornar idioma padrão
                return GetDefaultLanguage();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao determinar idioma atual");
                return GetDefaultLanguage();
            }
        }

        public string GetLanguageFromPath(string path)
        {
            if (string.IsNullOrEmpty(path) || path == "/")
                return string.Empty;

            var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);
            if (segments.Length == 0)
                return string.Empty;

            var firstSegment = segments[0].ToLowerInvariant();

            return SupportedLanguages.ContainsKey(firstSegment) ? firstSegment : string.Empty;
        }

        public List<string> GetSupportedLanguages()
        {
            return SupportedLanguages.Keys.ToList();
        }

        public string GetDefaultLanguage()
        {
            return "pt";
        }

        public string GetLanguageDisplayName(string languageCode)
        {
            return SupportedLanguages.TryGetValue(languageCode, out var displayName)
                ? displayName
                : languageCode;
        }

        public Dictionary<string, string> GetHreflangUrls(string currentUrl, string currentLanguage)
        {
            var cacheKey = $"hreflang_{currentUrl}_{currentLanguage}";

            if (_cache.TryGetValue(cacheKey, out Dictionary<string, string>? cachedUrls) && cachedUrls != null)
            {
                return cachedUrls;
            }

            var hreflangUrls = new Dictionary<string, string>();

            try
            {
                var baseUrl = RemoveLanguageFromUrl(currentUrl, currentLanguage);

                foreach (var language in SupportedLanguages.Keys)
                {
                    var url = language == GetDefaultLanguage()
                        ? baseUrl
                        : $"{baseUrl.TrimEnd('/')}/{language}";

                    hreflangUrls[language] = url;
                }

                // Adicionar x-default para o idioma padrão
                hreflangUrls["x-default"] = hreflangUrls[GetDefaultLanguage()];

                _cache.Set(cacheKey, hreflangUrls, TimeSpan.FromMinutes(15));
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao gerar URLs hreflang para {CurrentUrl}", currentUrl);
            }

            return hreflangUrls;
        }

        public string GetCultureInfo(string languageCode)
        {
            return LanguageCultures.TryGetValue(languageCode, out var culture) ? culture : "pt-BR";
        }

        public void SetLanguageCookie(HttpContext context, string languageCode)
        {
            if (!SupportedLanguages.ContainsKey(languageCode))
                return;

            var cookieOptions = new CookieOptions
            {
                Expires = DateTimeOffset.UtcNow.AddYears(1),
                HttpOnly = false,
                Secure = context.Request.IsHttps,
                SameSite = SameSiteMode.Lax
            };

            context.Response.Cookies.Append("preferred_language", languageCode, cookieOptions);
        }

        public string GenerateLanguageSwitcher(HttpContext context, string currentLanguage)
        {
            var currentUrl = $"{context.Request.Scheme}://{context.Request.Host}{context.Request.Path}";
            var hreflangUrls = GetHreflangUrls(currentUrl, currentLanguage);

            var switcher = new List<string>();

            foreach (var language in SupportedLanguages)
            {
                var isActive = language.Key == currentLanguage;
                var cssClass = isActive ? "active" : "";
                var url = hreflangUrls.TryGetValue(language.Key, out var langUrl) ? langUrl : "/";

                switcher.Add($"<a href=\"{url}\" class=\"language-link {cssClass}\" hreflang=\"{language.Key}\">{language.Value}</a>");
            }

            return string.Join("", switcher);
        }

        public bool IsRtlLanguage(string languageCode)
        {
            // Lista de idiomas RTL (Right-to-Left)
            var rtlLanguages = new[] { "ar", "he", "fa", "ur" };
            return rtlLanguages.Contains(languageCode);
        }

        public string GetLanguageDirection(string languageCode)
        {
            return IsRtlLanguage(languageCode) ? "rtl" : "ltr";
        }

        public bool IsValidLanguage(string languageCode)
        {
            return !string.IsNullOrEmpty(languageCode) && SupportedLanguages.ContainsKey(languageCode.ToLowerInvariant());
        }

        public string NormalizeLanguageCode(string languageCode)
        {
            if (string.IsNullOrEmpty(languageCode))
                return GetDefaultLanguage();

            var normalized = languageCode.ToLowerInvariant().Trim();

            // Handle common variations
            normalized = normalized switch
            {
                "pt-br" or "pt_br" or "portuguese" => "pt",
                "en-us" or "en_us" or "english" => "en",
                "es-es" or "es_es" or "spanish" or "español" => "es",
                _ => normalized
            };

            return IsValidLanguage(normalized) ? normalized : GetDefaultLanguage();
        }

        private string GetLanguageFromBrowser(HttpContext context)
        {
            try
            {
                var acceptLanguage = context.Request.Headers.AcceptLanguage.ToString();
                if (string.IsNullOrEmpty(acceptLanguage))
                    return string.Empty;

                // Parse Accept-Language header
                var languages = acceptLanguage
                    .Split(',')
                    .Select(lang => lang.Split(';')[0].Trim())
                    .Select(lang => lang.Length >= 2 ? lang.Substring(0, 2).ToLowerInvariant() : lang)
                    .Where(lang => SupportedLanguages.ContainsKey(lang));

                return languages.FirstOrDefault() ?? string.Empty;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao analisar Accept-Language header");
                return string.Empty;
            }
        }

        private string RemoveLanguageFromUrl(string url, string currentLanguage)
        {
            try
            {
                var uri = new Uri(url);
                var path = uri.AbsolutePath;

                if (currentLanguage != GetDefaultLanguage())
                {
                    var languagePrefix = $"/{currentLanguage}";
                    if (path.StartsWith(languagePrefix))
                    {
                        path = path.Substring(languagePrefix.Length);
                        if (string.IsNullOrEmpty(path))
                            path = "/";
                    }
                }

                return $"{uri.Scheme}://{uri.Host}{(uri.Port != 80 && uri.Port != 443 ? $":{uri.Port}" : "")}{path}";
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Erro ao remover idioma da URL {Url}", url);
                return url;
            }
        }
    }
}
