using ladaexpress.vn.Infrastructures.DTO.Models.Seo;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;

namespace ladaexpress.vn.Infrastructures.Services
{
    /// <summary>
    /// Implementation của IBreadcrumbService với cache support
    /// </summary>
    public class BreadcrumbService : IBreadcrumbService
    {
        private readonly IAppConfigService _appConfigService;
        private readonly IMemoryCache _memoryCache;
        private readonly IConfiguration _configuration;
        private readonly ILogger<BreadcrumbService> _logger;
        private readonly string _baseUrl;
        private readonly string _cacheKeyPrefix = "Breadcrumb_";

        public BreadcrumbService(
            IAppConfigService appConfigService,
            IMemoryCache memoryCache,
            IConfiguration configuration,
            ILogger<BreadcrumbService> logger)
        {
            _appConfigService = appConfigService;
            _memoryCache = memoryCache;
            _configuration = configuration;
            _logger = logger;
            _baseUrl = _configuration["SeoSettings:BaseUrl"] ?? "https://ladaexpress.vn";
        }

        public async Task<List<BreadcrumbItem>> GetHomeBreadcrumbsAsync()
        {
            var cacheKey = $"{_cacheKeyPrefix}Home";

            if (_memoryCache.TryGetValue(cacheKey, out List<BreadcrumbItem>? cached) && cached != null)
            {
                return cached;
            }

            var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");
            var breadcrumbs = await CreateCustomBreadcrumbsAsync((homeText, "/"));

            // Cache for 1 hour
            _memoryCache.Set(cacheKey, breadcrumbs, TimeSpan.FromHours(1));
            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> GetProductIndexBreadcrumbsAsync()
        {
            var cacheKey = $"{_cacheKeyPrefix}ProductIndex";

            if (_memoryCache.TryGetValue(cacheKey, out List<BreadcrumbItem>? cached) && cached != null)
            {
                return cached;
            }

            var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");
            var productText = await GetConfigValueAsync("SEO.Breadcrumb.ProductIndexText", "Dịch vụ");

            List<BreadcrumbItem> breadcrumbs;

            // Home > Products > Category > Product
            breadcrumbs = await CreateCustomBreadcrumbsAsync(
                (homeText, "/"),
                (productText, "/dich-vu")
            );

            // Cache for 30 minutes
            _memoryCache.Set(cacheKey, breadcrumbs, TimeSpan.FromMinutes(300));
            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> GetJobPostIndexBreadcrumbsAsync()
        {
            var cacheKey = $"{_cacheKeyPrefix}JobPostIndex";

            if (_memoryCache.TryGetValue(cacheKey, out List<BreadcrumbItem>? cached) && cached != null)
            {
                return cached;
            }

            var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");
            var productText = await GetConfigValueAsync("SEO.Breadcrumb.JobPostIndexText", "Tuyển dụng - Việc làm");

            List<BreadcrumbItem> breadcrumbs;

            // Home > Products > Category > Product
            breadcrumbs = await CreateCustomBreadcrumbsAsync(
                (homeText, "/"),
                (productText, "/tuyen-dung")
            );

            // Cache for 30 minutes
            _memoryCache.Set(cacheKey, breadcrumbs, TimeSpan.FromMinutes(300));
            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> GetProductBreadcrumbsAsync(int productId, string productName, string productUrl, string? categoryName = null, string? categoryUrl = null)
        {
            var cacheKey = $"{_cacheKeyPrefix}Product_{productId}";

            if (_memoryCache.TryGetValue(cacheKey, out List<BreadcrumbItem>? cached) && cached != null)
            {
                return cached;
            }

            var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");
            var productText = await GetConfigValueAsync("SEO.Breadcrumb.ProductText", "Dịch vụ");

            List<BreadcrumbItem> breadcrumbs;

            if (!string.IsNullOrEmpty(categoryName) && !string.IsNullOrEmpty(categoryUrl))
            {
                // Home > Products > Category > Product
                breadcrumbs = await CreateCustomBreadcrumbsAsync(
                    (homeText, "/"),
                    (productText, "/dich-vu"),
                    (categoryName, categoryUrl),
                    (productName, productUrl)
                );
            }
            else
            {
                // Home > Products > Product
                breadcrumbs = await CreateCustomBreadcrumbsAsync(
                    (homeText, "/"),
                    (productText, "/dich-vu"),
                    (productName, productUrl)
                );
            }

            // Cache for 30 minutes
            _memoryCache.Set(cacheKey, breadcrumbs, TimeSpan.FromMinutes(30));
            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> GetPostBreadcrumbsAsync(int postId, string postTitle, string postUrl, string? categoryName = null, string? categoryUrl = null)
        {
            var cacheKey = $"{_cacheKeyPrefix}Post_{postId}";

            if (_memoryCache.TryGetValue(cacheKey, out List<BreadcrumbItem>? cached) && cached != null)
            {
                return cached;
            }

            var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");
            var newsText = await GetConfigValueAsync("SEO.Breadcrumb.NewsText", "Tin tức");

            List<BreadcrumbItem> breadcrumbs;

            if (!string.IsNullOrEmpty(categoryName) && !string.IsNullOrEmpty(categoryUrl))
            {
                // Home > News > Category > Post
                breadcrumbs = await CreateCustomBreadcrumbsAsync(
                    (homeText, "/"),
                    (newsText, "/tin-tuc"),
                    (categoryName, categoryUrl),
                    (postTitle, postUrl)
                );
            }
            else
            {
                // Home > News > Post
                breadcrumbs = await CreateCustomBreadcrumbsAsync(
                    (homeText, "/"),
                    (newsText, "/tin-tuc"),
                    (postTitle, postUrl)
                );
            }

            // Cache for 30 minutes
            _memoryCache.Set(cacheKey, breadcrumbs, TimeSpan.FromMinutes(30));
            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> GetCategoryBreadcrumbsAsync(int categoryId, string categoryName, string categoryUrl, bool isProductCategory = true)
        {
            var cacheKey = $"{_cacheKeyPrefix}Category_{categoryId}_{isProductCategory}";

            if (_memoryCache.TryGetValue(cacheKey, out List<BreadcrumbItem>? cached) && cached != null)
            {
                return cached;
            }

            var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");

            List<BreadcrumbItem> breadcrumbs;

            if (isProductCategory)
            {
                var productText = await GetConfigValueAsync("SEO.Breadcrumb.ProductText", "Dịch vụ");
                breadcrumbs = await CreateCustomBreadcrumbsAsync(
                    (homeText, "/"),
                    (productText, "/dich-vu"),
                    (categoryName, categoryUrl)
                );
            }
            else
            {
                var newsText = await GetConfigValueAsync("SEO.Breadcrumb.NewsText", "Tin tức");
                breadcrumbs = await CreateCustomBreadcrumbsAsync(
                    (homeText, "/"),
                    (newsText, "/tin-tuc"),
                    (categoryName, categoryUrl)
                );
            }

            // Cache for 1 hour
            _memoryCache.Set(cacheKey, breadcrumbs, TimeSpan.FromHours(1));
            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> GetTagBreadcrumbsAsync(int tagId, string tagName, string tagUrl)
        {
            var cacheKey = $"{_cacheKeyPrefix}Tag_{tagId}";

            if (_memoryCache.TryGetValue(cacheKey, out List<BreadcrumbItem>? cached) && cached != null)
            {
                return cached;
            }

            var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");
            var tagText = await GetConfigValueAsync("SEO.Breadcrumb.TagText", "Từ khóa");

            var breadcrumbs = await CreateCustomBreadcrumbsAsync(
                (homeText, "/"),
                (tagText, "/tag"),
                (tagName, tagUrl)
            );

            // Cache for 1 hour
            _memoryCache.Set(cacheKey, breadcrumbs, TimeSpan.FromHours(1));
            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> GetSearchBreadcrumbsAsync(string query, string searchUrl)
        {
            var cacheKey = $"{_cacheKeyPrefix}Search_{query?.GetHashCode()}";

            if (_memoryCache.TryGetValue(cacheKey, out List<BreadcrumbItem>? cached) && cached != null)
            {
                return cached;
            }

            var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");
            var searchText = await GetConfigValueAsync("SEO.Breadcrumb.SearchText", "Tìm kiếm");

            List<BreadcrumbItem> breadcrumbs;

            if (!string.IsNullOrEmpty(query))
            {
                breadcrumbs = await CreateCustomBreadcrumbsAsync(
                    (homeText, "/"),
                    (searchText, "/tim-kiem"),
                    ($"Kết quả cho \"{query}\"", searchUrl)
                );
            }
            else
            {
                breadcrumbs = await CreateCustomBreadcrumbsAsync(
                    (homeText, "/"),
                    (searchText, searchUrl)
                );
            }

            // Cache for 15 minutes (search results change frequently)
            _memoryCache.Set(cacheKey, breadcrumbs, TimeSpan.FromMinutes(15));
            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> CreateCustomBreadcrumbsAsync(params (string name, string url)[] items)
        {
            var breadcrumbs = new List<BreadcrumbItem>();
            var baseUrl = await GetConfigValueAsync("SEO.BaseUrl", _baseUrl);

            for (int i = 0; i < items.Length; i++)
            {
                breadcrumbs.Add(new BreadcrumbItem
                {
                    Name = items[i].name,
                    Url = CreateCanonicalUrl(items[i].url, baseUrl),
                    Position = i + 1
                });
            }

            return breadcrumbs;
        }

        public async Task<List<BreadcrumbItem>> CreateFromPathAsync(string path, string currentPageName)
        {
            try
            {
                var homeText = await GetConfigValueAsync("SEO.Breadcrumb.HomeText", "Trang chủ");
                var segments = path.Split('/', StringSplitOptions.RemoveEmptyEntries);

                var breadcrumbs = new List<BreadcrumbItem>
                {
                    new BreadcrumbItem { Name = homeText, Url = await CreateCanonicalUrlAsync("/"), Position = 1 }
                };

                var currentPath = "";
                for (int i = 0; i < segments.Length - 1; i++) // Exclude last segment (current page)
                {
                    currentPath += "/" + segments[i];
                    var segmentName = await GetSegmentDisplayName(segments[i]);

                    breadcrumbs.Add(new BreadcrumbItem
                    {
                        Name = segmentName,
                        Url = await CreateCanonicalUrlAsync(currentPath),
                        Position = i + 2
                    });
                }

                // Add current page
                breadcrumbs.Add(new BreadcrumbItem
                {
                    Name = currentPageName,
                    Url = await CreateCanonicalUrlAsync(path),
                    Position = breadcrumbs.Count + 1
                });

                return breadcrumbs;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error creating breadcrumbs from path: {Path}", path);
                return await GetHomeBreadcrumbsAsync(); // Fallback to home breadcrumb
            }
        }

        public List<string> ValidateBreadcrumbs(List<BreadcrumbItem> breadcrumbs)
        {
            var errors = new List<string>();

            if (breadcrumbs == null || breadcrumbs.Count == 0)
            {
                errors.Add("Breadcrumbs list không được để trống");
                return errors;
            }

            // Check positions are sequential
            for (int i = 0; i < breadcrumbs.Count; i++)
            {
                if (breadcrumbs[i].Position != i + 1)
                {
                    errors.Add($"Position không đúng thứ tự tại vị trí {i}: expected {i + 1}, got {breadcrumbs[i].Position}");
                }
            }

            // Check for empty names or URLs
            foreach (var breadcrumb in breadcrumbs)
            {
                if (string.IsNullOrEmpty(breadcrumb.Name))
                {
                    errors.Add($"Breadcrumb tại position {breadcrumb.Position} có Name trống");
                }

                if (string.IsNullOrEmpty(breadcrumb.Url))
                {
                    errors.Add($"Breadcrumb tại position {breadcrumb.Position} có URL trống");
                }
            }

            // Check first breadcrumb is home
            if (breadcrumbs.Count > 0 && !breadcrumbs[0].Url.EndsWith("/"))
            {
                errors.Add("Breadcrumb đầu tiên nên là trang chủ (/)");
            }

            return errors;
        }

        #region Private Helper Methods

        private async Task<string> GetConfigValueAsync(string key, string defaultValue)
        {
            try
            {
                var value = await _appConfigService.GetConfigValueAsync(key, defaultValue);
                return string.IsNullOrEmpty(value) ? defaultValue : value;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Failed to get config value for key: {Key}, using default: {DefaultValue}", key, defaultValue);
                return defaultValue;
            }
        }

        private string CreateCanonicalUrl(string path, string baseUrl)
        {
            if (path.StartsWith("http"))
                return path;

            if (!path.StartsWith("/"))
                path = "/" + path;

            return $"{baseUrl.TrimEnd('/')}{path}";
        }

        private async Task<string> CreateCanonicalUrlAsync(string path)
        {
            var baseUrl = await GetConfigValueAsync("SEO.BaseUrl", _baseUrl);
            return CreateCanonicalUrl(path, baseUrl);
        }

        private async Task<string> GetSegmentDisplayName(string segment)
        {
            // Map common URL segments to display names
            var segmentMappings = new Dictionary<string, string>
            {
                {"dich-vu", await GetConfigValueAsync("SEO.Breadcrumb.ProductText", "Sản phẩm")},
                {"tin-tuc", await GetConfigValueAsync("SEO.Breadcrumb.NewsText", "Tin tức")},
                {"tag", await GetConfigValueAsync("SEO.Breadcrumb.TagText", "Thẻ")},
                {"tim-kiem", await GetConfigValueAsync("SEO.Breadcrumb.SearchText", "Tìm kiếm")},
                {"lien-he", "Liên hệ"},
                {"gioi-thieu", "Giới thiệu"},
                {"tuyen-dung", "Tuyển dụng"}
            };

            if (segmentMappings.ContainsKey(segment))
            {
                return segmentMappings[segment];
            }

            // Convert slug to display name (basic implementation)
            return segment.Replace("-", " ").Replace("_", " ")
                .Split(' ')
                .Select(word => char.ToUpper(word[0]) + word.Substring(1).ToLower())
                .Aggregate((current, next) => current + " " + next);
        }

        #endregion
    }
}