using ladaexpress.vn.Infrastructures.DTO.Models.Seo;
using ladaexpress.vn.Infrastructures.Services;
using Microsoft.Extensions.Configuration;
using System.Text.Json;

namespace ladaexpress.vn.Infrastructures.Services.Seo
{
    /// <summary>
    /// Implementation của Structured Data Service
    /// </summary>
    public class StructuredDataService : IStructuredDataService
    {
        private readonly IConfiguration _configuration;
        private readonly IAppConfigService _appConfigService;
        private readonly string _baseUrl;
        private readonly string _siteName;

        public StructuredDataService(IConfiguration configuration, IAppConfigService appConfigService)
        {
            _configuration = configuration;
            _appConfigService = appConfigService;
            _baseUrl = _configuration["SeoSettings:BaseUrl"] ?? "https://ladaexpress.vn";
            _siteName = _configuration["SeoSettings:SiteName"] ?? "LADA Express";
        }

        /// <summary>
        /// Tạo JsonSerializerOptions chuẩn cho structured data
        /// </summary>
        private static JsonSerializerOptions GetJsonSerializerOptions()
        {
            return new JsonSerializerOptions
            {
                PropertyNamingPolicy = null, // Không sử dụng camelCase để giữ nguyên @context, @type
                WriteIndented = false,
                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            };
        }

        public string GenerateOrganizationSchema()
        {
            var organization = new OrganizationSchema
            {
                Name = "LADA Express",
                Url = _baseUrl,
                Logo = $"{_baseUrl}/images/logo.svg",
                Description = "Dịch vụ gửi hàng nhanh chóng, uy tín trên toàn quốc. Cam kết giao hàng đúng hẹn, giá cả hợp lý.",
                ContactPoint = new ContactPointSchema
                {
                    Telephone = "+84-xxx-xxx-xxx",
                    ContactType = "customer service",
                    Email = "contact@ladaexpress.vn"
                },
                Address = new AddressSchema
                {
                    StreetAddress = "Địa chỉ công ty",
                    AddressLocality = "Hà Nội",
                    AddressRegion = "Hà Nội",
                    PostalCode = "100000",
                    AddressCountry = "VN"
                },
                SameAs = new List<string>
                {
                    "https://www.facebook.com/ladaexpress",
                    "https://www.linkedin.com/company/ladaexpress"
                }
            };

            // Custom serialization to include @context and @type
            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = organization.Type,
                ["name"] = organization.Name,
                ["url"] = organization.Url,
                ["logo"] = organization.Logo,
                ["description"] = organization.Description,
                ["contactPoint"] = new Dictionary<string, object>
                {
                    ["@type"] = organization.ContactPoint.Type,
                    ["telephone"] = organization.ContactPoint.Telephone,
                    ["contactType"] = organization.ContactPoint.ContactType,
                    ["email"] = organization.ContactPoint.Email
                },
                ["address"] = new Dictionary<string, object>
                {
                    ["@type"] = organization.Address.Type,
                    ["streetAddress"] = organization.Address.StreetAddress,
                    ["addressLocality"] = organization.Address.AddressLocality,
                    ["addressRegion"] = organization.Address.AddressRegion,
                    ["postalCode"] = organization.Address.PostalCode,
                    ["addressCountry"] = organization.Address.AddressCountry
                },
                ["sameAs"] = organization.SameAs
            };

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public string GenerateWebsiteSchema()
        {
            var website = new WebsiteSchema
            {
                Name = _siteName,
                Url = _baseUrl,
                PotentialAction = new SearchActionSchema
                {
                    Target = $"{_baseUrl}/tim-kiem?q={{search_term_string}}",
                    QueryInput = "required name=search_term_string"
                }
            };

            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = website.Type,
                ["name"] = website.Name,
                ["url"] = website.Url,
                ["potentialAction"] = new Dictionary<string, object>
                {
                    ["@type"] = website.PotentialAction.Type,
                    ["target"] = website.PotentialAction.Target,
                    ["query-input"] = website.PotentialAction.QueryInput
                }
            };

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public string GenerateArticleSchema(ArticleSchema article)
        {
            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = article.Type,
                ["headline"] = article.Headline,
                ["description"] = article.Description,
                ["image"] = article.Image,
                ["url"] = article.Url,
                ["datePublished"] = article.DatePublished.ToString("yyyy-MM-ddTHH:mm:ssZ"),
                ["dateModified"] = article.DateModified.ToString("yyyy-MM-ddTHH:mm:ssZ"),
                ["author"] = new Dictionary<string, object>
                {
                    ["@type"] = article.Author.Type,
                    ["name"] = article.Author.Name,
                    ["url"] = article.Author.Url
                },
                ["publisher"] = new Dictionary<string, object>
                {
                    ["@type"] = article.Publisher.Type,
                    ["name"] = article.Publisher.Name,
                    ["logo"] = new Dictionary<string, object>
                    {
                        ["@type"] = "ImageObject",
                        ["url"] = article.Publisher.Logo
                    }
                },
                ["mainEntityOfPage"] = new Dictionary<string, object>
                {
                    ["@type"] = "WebPage",
                    ["@id"] = article.MainEntityOfPage
                }
            };

            if (article.Keywords.Any())
            {
                jsonObject["keywords"] = article.Keywords;
            }

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public string GenerateProductSchema(ProductSchema product)
        {
            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = product.Type,
                ["name"] = product.Name,
                ["description"] = product.Description,
                ["image"] = product.Image,
                ["url"] = product.Url,
                ["brand"] = new Dictionary<string, object>
                {
                    ["@type"] = "Brand",
                    ["name"] = product.Brand
                }
            };

            if (product.Offers != null)
            {
                jsonObject["offers"] = new Dictionary<string, object>
                {
                    ["@type"] = product.Offers.Type,
                    ["priceCurrency"] = product.Offers.PriceCurrency,
                    ["price"] = product.Offers.Price,
                    ["availability"] = product.Offers.Availability,
                    ["url"] = product.Offers.Url
                };
            }

            if (product.AggregateRating != null)
            {
                jsonObject["aggregateRating"] = new Dictionary<string, object>
                {
                    ["@type"] = product.AggregateRating.Type,
                    ["ratingValue"] = product.AggregateRating.RatingValue,
                    ["bestRating"] = product.AggregateRating.BestRating,
                    ["worstRating"] = product.AggregateRating.WorstRating,
                    ["ratingCount"] = product.AggregateRating.RatingCount
                };
            }

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public string GenerateBreadcrumbSchema(List<BreadcrumbItem> breadcrumbs)
        {
            var itemListElements = breadcrumbs.Select(b => new Dictionary<string, object>
            {
                ["@type"] = "ListItem",
                ["position"] = b.Position,
                ["name"] = b.Name,
                ["item"] = b.Url
            }).ToList();

            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = "BreadcrumbList",
                ["itemListElement"] = itemListElements
            };

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public string GenerateFAQSchema(FAQPageSchema faq)
        {
            var mainEntity = faq.MainEntity.Select(q => new Dictionary<string, object>
            {
                ["@type"] = q.Type,
                ["name"] = q.Name,
                ["acceptedAnswer"] = new Dictionary<string, object>
                {
                    ["@type"] = q.AcceptedAnswer.Type,
                    ["text"] = q.AcceptedAnswer.Text
                }
            }).ToList();

            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = faq.Type,
                ["mainEntity"] = mainEntity
            };

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public string CombineSchemas(params string[] schemas)
        {
            if (schemas == null || schemas.Length == 0)
                return "";

            if (schemas.Length == 1)
                return schemas[0];

            // Combine multiple schemas into an array
            var combinedSchemas = schemas.Where(s => !string.IsNullOrEmpty(s)).ToList();

            if (combinedSchemas.Count == 1)
                return combinedSchemas[0];

            var jsonObjects = new List<object>();
            foreach (var schema in combinedSchemas)
            {
                try
                {
                    var obj = JsonSerializer.Deserialize<object>(schema);
                    jsonObjects.Add(obj);
                }
                catch
                {
                    // Skip invalid JSON
                    continue;
                }
            }

            return JsonSerializer.Serialize(jsonObjects, GetJsonSerializerOptions());
        }

        public async Task<string> GetProductStructuredDataAsync(int productId, string name, string description, string image, string url, decimal? price = null)
        {
            var baseUrl = await GetConfigValueAsync("SEO.BaseUrl", _baseUrl);
            var defaultImage = await GetConfigValueAsync("SEO.DefaultImage", "/images/logo.svg");
            var currency = await GetConfigValueAsync("SEO.Service.Currency", "VND");
            var organizationName = await GetConfigValueAsync("SEO.Organization.Name", "LADA Express");
            var organizationUrl = await GetConfigValueAsync("SEO.Organization.Url", baseUrl);

            // Sử dụng Service schema thay vì Product schema cho dịch vụ
            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = "Service",
                ["name"] = name,
                ["description"] = description,
                ["image"] = string.IsNullOrEmpty(image) ? CreateCanonicalUrl(defaultImage, baseUrl) : CreateCanonicalUrl(image, baseUrl),
                ["url"] = CreateCanonicalUrl(url, baseUrl),
                ["provider"] = new Dictionary<string, object>
                {
                    ["@type"] = "Organization",
                    ["name"] = organizationName,
                    ["url"] = organizationUrl
                },
                ["serviceType"] = "Logistics",
                ["category"] = "Transportation and Logistics",
                ["areaServed"] = new Dictionary<string, object>
                {
                    ["@type"] = "Country",
                    ["name"] = "Vietnam"
                }
            };

            // Nếu có giá thì thêm thông tin offers
            if (price.HasValue && price.Value > 0)
            {
                jsonObject["offers"] = new Dictionary<string, object>
                {
                    ["@type"] = "Offer",
                    ["price"] = price.Value,
                    ["priceCurrency"] = currency,
                    ["url"] = CreateCanonicalUrl(url, baseUrl),
                    ["availability"] = "https://schema.org/InStock",
                    ["validFrom"] = DateTime.Now.ToString("yyyy-MM-dd")
                };
            }

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public async Task<string> GetArticleStructuredDataAsync(int postId, string title, string description, string image, string url,
            string author, DateTime publishedDate, DateTime? modifiedDate = null)
        {
            var baseUrl = await GetConfigValueAsync("SEO.BaseUrl", _baseUrl);
            var defaultImage = await GetConfigValueAsync("SEO.DefaultImage", "/images/logo.svg");
            var defaultAuthor = await GetConfigValueAsync("SEO.News.DefaultAuthor", "LADA Express");
            var publisherName = await GetConfigValueAsync("SEO.News.PublisherName", "LADA Express");
            var organizationLogo = await GetConfigValueAsync("SEO.Organization.Logo", $"{baseUrl}/images/logo.png");

            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = "Article",
                ["headline"] = title,
                ["description"] = description,
                ["image"] = string.IsNullOrEmpty(image) ? CreateCanonicalUrl(defaultImage, baseUrl) : CreateCanonicalUrl(image, baseUrl),
                ["url"] = CreateCanonicalUrl(url, baseUrl),
                ["datePublished"] = publishedDate.ToString("yyyy-MM-ddTHH:mm:ssZ"),
                ["dateModified"] = (modifiedDate ?? publishedDate).ToString("yyyy-MM-ddTHH:mm:ssZ"),
                ["mainEntityOfPage"] = CreateCanonicalUrl(url, baseUrl),
                ["author"] = new Dictionary<string, object>
                {
                    ["@type"] = "Person",
                    ["name"] = !string.IsNullOrEmpty(author) ? author : defaultAuthor
                },
                ["publisher"] = new Dictionary<string, object>
                {
                    ["@type"] = "Organization",
                    ["name"] = publisherName,
                    ["logo"] = organizationLogo,
                    ["url"] = baseUrl
                }
            };

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public async Task<string> GetCollectionPageStructuredDataAsync(int categoryId, string name, string description, string url, int? totalItems = null)
        {
            var baseUrl = await GetConfigValueAsync("SEO.BaseUrl", _baseUrl);

            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = "CollectionPage",
                ["name"] = name,
                ["description"] = description,
                ["url"] = CreateCanonicalUrl(url, baseUrl)
            };

            if (totalItems.HasValue)
            {
                jsonObject["numberOfItems"] = totalItems.Value;
            }

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public async Task<string> GetBreadcrumbStructuredDataAsync(List<BreadcrumbItem> breadcrumbItems)
        {
            var baseUrl = await GetConfigValueAsync("SEO.BaseUrl", _baseUrl);

            var itemListElements = breadcrumbItems.Select(item => new Dictionary<string, object>
            {
                ["@type"] = "ListItem",
                ["position"] = item.Position,
                ["name"] = item.Name,
                ["item"] = item.Url.StartsWith("http") ? item.Url : CreateCanonicalUrl(item.Url, baseUrl)
            }).ToList();

            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = "BreadcrumbList",
                ["itemListElement"] = itemListElements
            };

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        public async Task<string> GetFAQStructuredDataAsync(List<FAQItem> faqItems)
        {
            if (faqItems == null || !faqItems.Any())
                return string.Empty;

            var faqPage = new FAQPageSchema
            {
                MainEntity = faqItems.Select(item => new QuestionSchema
                {
                    Name = item.Question,
                    AcceptedAnswer = new AnswerSchema
                    {
                        Text = item.Answer
                    }
                }).ToList()
            };

            return JsonSerializer.Serialize(faqPage, GetJsonSerializerOptions());
        }

        /// <summary>
        /// Tạo JobPosting structured data cho trang tuyển dụng
        /// </summary>
        /// <param name="jobId">ID công việc</param>
        /// <param name="title">Tiêu đề công việc</param>
        /// <param name="description">Mô tả công việc</param>
        /// <param name="workingAddress">Địa chỉ làm việc</param>
        /// <param name="minSalary">Lương tối thiểu</param>
        /// <param name="maxSalary">Lương tối đa</param>
        /// <param name="currency">Đơn vị tiền tệ</param>
        /// <param name="employmentType">Loại hình công việc</param>
        /// <param name="datePosted">Ngày đăng</param>
        /// <param name="validThrough">Hạn nộp hồ sơ</param>
        /// <param name="url">URL trang tuyển dụng</param>
        /// <returns></returns>
        public async Task<string> GetJobPostingStructuredDataAsync(
            int jobId,
            string title,
            string description,
            string workingAddress,
            decimal? minSalary = null,
            decimal? maxSalary = null,
            string currency = "VND",
            string employmentType = "FULL_TIME",
            DateTime? datePosted = null,
            DateTime? validThrough = null,
            string url = "")
        {
            var baseUrl = await GetConfigValueAsync("SEO.BaseUrl", _baseUrl);
            var organizationName = await GetConfigValueAsync("SEO.Organization.Name", "LADA Express");
            var organizationUrl = await GetConfigValueAsync("SEO.Organization.Url", baseUrl);
            var organizationLogo = await GetConfigValueAsync("SEO.Organization.Logo", $"{baseUrl}/images/logo.png");
            var defaultCurrency = await GetConfigValueAsync("SEO.Job.Currency", "VND");

            var jsonObject = new Dictionary<string, object>
            {
                ["@context"] = "https://schema.org",
                ["@type"] = "JobPosting",
                ["title"] = title,
                ["description"] = description,
                ["datePosted"] = (datePosted ?? DateTime.Now).ToString("yyyy-MM-dd"),
                ["employmentType"] = employmentType.ToUpper(),
                ["hiringOrganization"] = new Dictionary<string, object>
                {
                    ["@type"] = "Organization",
                    ["name"] = organizationName,
                    ["sameAs"] = organizationUrl,
                    ["logo"] = organizationLogo
                },
                ["jobLocation"] = new Dictionary<string, object>
                {
                    ["@type"] = "Place",
                    ["address"] = new Dictionary<string, object>
                    {
                        ["@type"] = "PostalAddress",
                        ["addressLocality"] = workingAddress,
                        ["addressCountry"] = "VN"
                    }
                },
                ["url"] = string.IsNullOrEmpty(url) ? baseUrl : CreateCanonicalUrl(url, baseUrl)
            };

            if (validThrough.HasValue)
            {
                jsonObject["validThrough"] = validThrough.Value.ToString("yyyy-MM-dd");
            }

            // Thêm thông tin lương nếu có
            if (minSalary.HasValue || maxSalary.HasValue)
            {
                jsonObject["baseSalary"] = new Dictionary<string, object>
                {
                    ["@type"] = "MonetaryAmount",
                    ["currency"] = !string.IsNullOrEmpty(currency) ? currency : defaultCurrency,
                    ["value"] = new Dictionary<string, object>
                    {
                        ["@type"] = "QuantitativeValue",
                        ["minValue"] = minSalary,
                        ["maxValue"] = maxSalary,
                        ["unitText"] = "MONTH"
                    }
                };
            }

            return JsonSerializer.Serialize(jsonObject, GetJsonSerializerOptions());
        }

        /// <summary>
        /// Helper method để lấy config từ AppConfig với fallback
        /// </summary>
        private async Task<string> GetConfigValueAsync(string key, string defaultValue)
        {
            try
            {
                var value = await _appConfigService.GetConfigValueAsync(key, defaultValue);
                return string.IsNullOrEmpty(value) ? defaultValue : value;
            }
            catch
            {
                return defaultValue;
            }
        }

        /// <summary>
        /// Helper method để tạo canonical URL
        /// </summary>
        private string CreateCanonicalUrl(string path, string baseUrl)
        {
            if (path.StartsWith("http"))
                return path;

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

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