using System.Text.RegularExpressions;
using TaxBaik.Application.Services;

namespace TaxBaik.Web.Services;

/// <summary>
/// Sitemap 및 RSS 피드의 정합성 검증
/// </summary>
public class SitemapValidationService
{
    private readonly BlogService _blogService;
    private readonly ILogger<SitemapValidationService> _logger;

    public SitemapValidationService(BlogService blogService, ILogger<SitemapValidationService> logger)
    {
        _blogService = blogService;
        _logger = logger;
    }

    /// <summary>
    /// Sitemap 검증 결과
    /// </summary>
    public class SitemapValidationResult
    {
        public bool IsValid { get; set; }
        public List<string> Errors { get; set; } = [];
        public List<string> Warnings { get; set; } = [];
        public int TotalUrls { get; set; }
        public int BlogPostUrls { get; set; }
        public DateTime ValidatedAt { get; set; } = DateTime.UtcNow;
    }

    /// <summary>
    /// Sitemap 전체 검증
    /// </summary>
    public async Task<SitemapValidationResult> ValidateSitemapAsync()
    {
        var result = new SitemapValidationResult();

        try
        {
            // 1. 정적 페이지 검증
            var staticUrls = GetStaticUrls();
            ValidateUrls(staticUrls, result);

            result.TotalUrls = staticUrls.Count;

            // 2. 동적 블로그 포스트 검증
            var (posts, _) = await _blogService.GetPublishedPagedAsync(1, 1000, categoryId: null, ct: default);
            var blogUrls = posts.Select(p => $"https://www.taxbaik.com/blog/{p.Slug}").ToList();

            ValidateUrls(blogUrls, result);

            result.TotalUrls += blogUrls.Count;
            result.BlogPostUrls = blogUrls.Count;

            // 3. 중복 검증
            var allUrls = staticUrls.Concat(blogUrls).ToList();
            var duplicates = allUrls.GroupBy(u => u)
                .Where(g => g.Count() > 1)
                .Select(g => g.Key)
                .ToList();

            if (duplicates.Any())
            {
                result.Errors.Add($"중복 URL 발견: {string.Join(", ", duplicates)}");
            }

            // 4. 블로그 포스트 날짜 검증
            foreach (var post in posts)
            {
                if (post.PublishedAt == null || post.PublishedAt == default)
                {
                    result.Warnings.Add($"포스트 '{post.Slug}'의 발행일이 없습니다.");
                }
            }

            result.IsValid = !result.Errors.Any();
        }
        catch (Exception ex)
        {
            result.Errors.Add($"검증 실패: {ex.Message}");
            result.IsValid = false;
        }

        _logger.LogInformation("Sitemap 검증 완료: {IsValid}, 총 {TotalUrls}개 URL, {BlogPostUrls}개 포스트",
            result.IsValid, result.TotalUrls, result.BlogPostUrls);

        return result;
    }

    /// <summary>
    /// RSS 피드 검증
    /// </summary>
    public async Task<SitemapValidationResult> ValidateRssFeedAsync()
    {
        var result = new SitemapValidationResult();

        try
        {
            var (posts, _) = await _blogService.GetPublishedPagedAsync(1, 50, categoryId: null, ct: default);

            if (!posts.Any())
            {
                result.Warnings.Add("RSS 피드에 포스트가 없습니다.");
            }

            // 필수 필드 검증
            var postsList = posts.ToList();
            foreach (var post in postsList)
            {
                var errors = new List<string>();

                if (string.IsNullOrEmpty(post.Title))
                    errors.Add("제목 없음");

                if (string.IsNullOrEmpty(post.Slug))
                    errors.Add("Slug 없음");

                if (string.IsNullOrEmpty(post.Content))
                    errors.Add("콘텐츠 없음");

                if (post.PublishedAt == null || post.PublishedAt == default)
                    errors.Add("발행일 없음");

                if (errors.Any())
                {
                    result.Errors.Add($"포스트 '{post.Title}': {string.Join(", ", errors)}");
                }

                // GUID 유효성 (URL 형식)
                var guid = $"https://www.taxbaik.com/blog/{post.Slug}";
                if (!Uri.TryCreate(guid, UriKind.Absolute, out _))
                {
                    result.Errors.Add($"GUID 유효하지 않음: {guid}");
                }

                // pubDate 형식 검증 (RFC 2822)
                if (post.PublishedAt.HasValue)
                {
                    try
                    {
                        var rfc2822 = post.PublishedAt.Value.ToString("R"); // RFC 2822 형식
                        if (string.IsNullOrEmpty(rfc2822))
                            result.Warnings.Add($"포스트 '{post.Slug}' pubDate 형식 변환 실패");
                    }
                    catch
                    {
                        result.Errors.Add($"포스트 '{post.Slug}' pubDate 형식 오류");
                    }
                }
            }

            result.TotalUrls = postsList.Count;
            result.IsValid = !result.Errors.Any();
        }
        catch (Exception ex)
        {
            result.Errors.Add($"RSS 검증 실패: {ex.Message}");
            result.IsValid = false;
        }

        _logger.LogInformation("RSS 검증 완료: {IsValid}, 총 {TotalUrls}개 포스트",
            result.IsValid, result.TotalUrls);

        return result;
    }

    /// <summary>
    /// Sitemap과 RSS의 일관성 검증
    /// </summary>
    public async Task<SitemapValidationResult> ValidateConsistencyAsync()
    {
        var result = new SitemapValidationResult();

        try
        {
            var sitemapValidation = await ValidateSitemapAsync();
            var rssValidation = await ValidateRssFeedAsync();

            // 에러 통합
            result.Errors.AddRange(sitemapValidation.Errors);
            result.Errors.AddRange(rssValidation.Errors);

            // 경고 통합
            result.Warnings.AddRange(sitemapValidation.Warnings);
            result.Warnings.AddRange(rssValidation.Warnings);

            // 블로그 포스트 수 비교
            if (sitemapValidation.BlogPostUrls != rssValidation.TotalUrls)
            {
                result.Warnings.Add(
                    $"Sitemap의 블로그 포스트({sitemapValidation.BlogPostUrls})와 " +
                    $"RSS 포스트({rssValidation.TotalUrls}) 수가 다릅니다. " +
                    $"(Sitemap은 전체, RSS는 최근 50개)"
                );
            }

            result.IsValid = !result.Errors.Any();
            result.TotalUrls = sitemapValidation.TotalUrls;
            result.BlogPostUrls = sitemapValidation.BlogPostUrls;
        }
        catch (Exception ex)
        {
            result.Errors.Add($"일관성 검증 실패: {ex.Message}");
            result.IsValid = false;
        }

        return result;
    }

    /// <summary>
    /// URL 형식 검증
    /// </summary>
    private static void ValidateUrls(List<string> urls, SitemapValidationResult result)
    {
        foreach (var url in urls)
        {
            // URL 형식 검증
            if (!Uri.TryCreate(url, UriKind.Absolute, out var uri))
            {
                result.Errors.Add($"유효하지 않은 URL: {url}");
                continue;
            }

            // HTTPS 검증
            if (uri.Scheme != "https")
            {
                result.Warnings.Add($"HTTPS가 아닌 URL: {url}");
            }

            // 도메인 검증
            if (uri.Host != "www.taxbaik.com" && uri.Host != "taxbaik.com")
            {
                result.Errors.Add($"잘못된 도메인: {url}");
            }
        }
    }

    /// <summary>
    /// 정적 페이지 URL 목록
    /// </summary>
    private static List<string> GetStaticUrls()
    {
            var baseUrl = "https://www.taxbaik.com";
        return new List<string>
        {
            $"{baseUrl}",
            $"{baseUrl}/about",
            $"{baseUrl}/services",
            $"{baseUrl}/contact",
            $"{baseUrl}/privacy",
            $"{baseUrl}/terms",
            $"{baseUrl}/blog",
            $"{baseUrl}/faq",
            $"{baseUrl}/announcement",
            $"{baseUrl}/inquiry"
        };
    }
}
