using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System.Text;

namespace ladaexpress.vn.Infrastructures.Services
{
    /// <summary>
    /// Implementation của IRobotsService
    /// </summary>
    public class RobotsService : IRobotsService
    {
        private readonly IAppConfigService _appConfigService;
        private readonly IConfiguration _configuration;
        private readonly IHostEnvironment _hostEnvironment;
        private readonly ILogger<RobotsService> _logger;
        private readonly string _baseUrl;

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

        public async Task<string> GenerateRobotsTxtAsync()
        {
            try
            {
                if (_hostEnvironment.IsDevelopment())
                {
                    return await GenerateDevRobotsTxtAsync();
                }
                else
                {
                    return await GenerateProdRobotsTxtAsync();
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error generating robots.txt");
                throw;
            }
        }

        public async Task<string> GenerateDevRobotsTxtAsync()
        {
            try
            {
                var sb = new StringBuilder();

                // Block all crawlers in development
                sb.AppendLine("# Robots.txt for LADA Express (Development Environment)");
                sb.AppendLine("# Generated on: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                sb.AppendLine();
                sb.AppendLine("User-agent: *");
                sb.AppendLine("Disallow: /");
                sb.AppendLine();
                sb.AppendLine("# Development environment - crawling disabled for all bots");

                return sb.ToString();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error generating dev robots.txt");
                throw;
            }
        }

        public async Task<string> GenerateProdRobotsTxtAsync()
        {
            try
            {
                var sb = new StringBuilder();
                var baseUrl = await GetConfigValueAsync("SEO.BaseUrl", _baseUrl);

                // Header
                sb.AppendLine("# Robots.txt for LADA Express");
                sb.AppendLine("# Generated on: " + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                sb.AppendLine("# Website: " + baseUrl);
                sb.AppendLine();

                // Main crawlers (Google, Bing, etc.)
                sb.AppendLine("User-agent: Googlebot");
                sb.AppendLine("Allow: /");
                sb.AppendLine("Disallow: /admin/");
                sb.AppendLine("Disallow: /api/");
                sb.AppendLine("Disallow: /*?*");  // Disallow URLs with query parameters
                sb.AppendLine("Crawl-delay: 1");
                sb.AppendLine();

                sb.AppendLine("User-agent: Bingbot");
                sb.AppendLine("Allow: /");
                sb.AppendLine("Disallow: /admin/");
                sb.AppendLine("Disallow: /api/");
                sb.AppendLine("Disallow: /*?*");
                sb.AppendLine("Crawl-delay: 2");
                sb.AppendLine();

                // Facebook crawler
                sb.AppendLine("User-agent: facebookexternalhit");
                sb.AppendLine("Allow: /");
                sb.AppendLine("Disallow: /admin/");
                sb.AppendLine("Disallow: /api/");
                sb.AppendLine();

                // General crawlers
                sb.AppendLine("User-agent: *");
                sb.AppendLine("Allow: /");

                // Disallow sensitive areas
                var disallowPaths = await GetDisallowPathsAsync();
                foreach (var path in disallowPaths)
                {
                    sb.AppendLine($"Disallow: {path}");
                }

                sb.AppendLine("Crawl-delay: 3");
                sb.AppendLine();

                // Block malicious bots
                var blockedBots = await GetBlockedBotsAsync();
                foreach (var bot in blockedBots)
                {
                    sb.AppendLine($"User-agent: {bot}");
                    sb.AppendLine("Disallow: /");
                    sb.AppendLine();
                }

                // Sitemap location
                sb.AppendLine($"Sitemap: {baseUrl}/sitemap.xml");
                sb.AppendLine($"Sitemap: {baseUrl}/sitemap-index.xml");

                return sb.ToString();
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error generating production robots.txt");
                throw;
            }
        }

        public List<string> ValidateRobotsTxt(string robotsTxt)
        {
            var errors = new List<string>();

            try
            {
                if (string.IsNullOrWhiteSpace(robotsTxt))
                {
                    errors.Add("Robots.txt content is empty");
                    return errors;
                }

                var lines = robotsTxt.Split('\n', StringSplitOptions.RemoveEmptyEntries);
                var hasUserAgent = false;
                var currentUserAgent = "";

                foreach (var line in lines)
                {
                    var trimmedLine = line.Trim();

                    // Skip comments and empty lines
                    if (string.IsNullOrEmpty(trimmedLine) || trimmedLine.StartsWith("#"))
                        continue;

                    // Check for proper directive format
                    if (!trimmedLine.Contains(':'))
                    {
                        errors.Add($"Invalid directive format: {trimmedLine}");
                        continue;
                    }

                    var parts = trimmedLine.Split(':', 2);
                    var directive = parts[0].Trim().ToLower();
                    var value = parts[1].Trim();

                    switch (directive)
                    {
                        case "user-agent":
                            hasUserAgent = true;
                            currentUserAgent = value;
                            if (string.IsNullOrEmpty(value))
                            {
                                errors.Add("User-agent cannot be empty");
                            }
                            break;

                        case "disallow":
                        case "allow":
                            if (!hasUserAgent)
                            {
                                errors.Add($"{directive} directive must come after User-agent");
                            }
                            if (!string.IsNullOrEmpty(value) && !value.StartsWith("/"))
                            {
                                errors.Add($"Path in {directive} should start with '/': {value}");
                            }
                            break;

                        case "crawl-delay":
                            if (!hasUserAgent)
                            {
                                errors.Add("Crawl-delay directive must come after User-agent");
                            }
                            if (!int.TryParse(value, out int delay) || delay < 0)
                            {
                                errors.Add($"Invalid crawl-delay value: {value}");
                            }
                            break;

                        case "sitemap":
                            if (!Uri.IsWellFormedUriString(value, UriKind.Absolute))
                            {
                                errors.Add($"Invalid sitemap URL: {value}");
                            }
                            break;

                        default:
                            // Unknown directive - warning, not error
                            break;
                    }
                }

                if (!hasUserAgent)
                {
                    errors.Add("Robots.txt must contain at least one User-agent directive");
                }

                // Check file size
                var sizeInBytes = Encoding.UTF8.GetBytes(robotsTxt).Length;
                if (sizeInBytes > 500 * 1024) // 500KB limit
                {
                    errors.Add($"Robots.txt file is too large: {sizeInBytes / 1024}KB (max 500KB)");
                }

                return errors;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error validating robots.txt");
                errors.Add($"Validation error: {ex.Message}");
                return errors;
            }
        }

        public async Task<string> SaveRobotsTxtAsync(string robotsTxt)
        {
            try
            {
                var webRootPath = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot");
                if (!Directory.Exists(webRootPath))
                {
                    Directory.CreateDirectory(webRootPath);
                }

                var filePath = Path.Combine(webRootPath, "robots.txt");
                await File.WriteAllTextAsync(filePath, robotsTxt, Encoding.UTF8);

                _logger.LogInformation("Saved robots.txt to {FilePath}", filePath);
                return filePath;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error saving robots.txt");
                throw;
            }
        }

        public async Task<List<string>> GetRobotsRecommendationsAsync()
        {
            try
            {
                var recommendations = new List<string>();

                if (_hostEnvironment.IsDevelopment())
                {
                    recommendations.Add("🔒 Development environment: All crawlers are blocked");
                    recommendations.Add("✅ This prevents search engines from indexing your development site");
                }
                else
                {
                    recommendations.Add("🤖 Major search engines (Google, Bing) are allowed with appropriate crawl delays");
                    recommendations.Add("🚫 Admin and API paths are blocked to protect sensitive areas");
                    recommendations.Add("📊 Malicious bots are blocked to reduce server load");
                    recommendations.Add("🗺️ Sitemap locations are specified for better crawling");
                    recommendations.Add("⚡ Crawl delays are set to prevent server overload");
                }

                // Additional recommendations based on config
                var hasAnalytics = await GetConfigValueAsync("SEO.Analytics.Enabled", "false");
                if (hasAnalytics.ToLower() == "true")
                {
                    recommendations.Add("📈 Analytics tracking is enabled - consider allowing analytics bots");
                }

                var hasSocialMedia = await GetConfigValueAsync("SEO.SocialMedia.Enabled", "false");
                if (hasSocialMedia.ToLower() == "true")
                {
                    recommendations.Add("📱 Social media crawlers (Facebook, Twitter) are allowed for rich previews");
                }

                return recommendations;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Error getting robots recommendations");
                return new List<string> { "❌ Error generating recommendations" };
            }
        }

        #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
            {
                return defaultValue;
            }
        }

        private async Task<List<string>> GetDisallowPathsAsync()
        {
            var defaultPaths = new List<string>
            {
                "/admin/",
                "/api/",
                "/Account/",
                "/Identity/",
                "/*.json",
                "/scripts/",
                "/bin/",
                "/obj/",
                "/temp/",
                "/cache/",
                "/logs/",
                "/backup/",
                "/test/",
                "/staging/",
                "/*sessionid*",
                "/*utm_*",
                "/*fbclid*",
                "/*gclid*",
                "/search?*",
                "/filter?*",
                "/sort?*"
            };

            try
            {
                var customPaths = await GetConfigValueAsync("SEO.Robots.DisallowPaths", "");
                if (!string.IsNullOrEmpty(customPaths))
                {
                    var customPathsList = customPaths.Split(',', StringSplitOptions.RemoveEmptyEntries)
                        .Select(p => p.Trim())
                        .Where(p => !string.IsNullOrEmpty(p))
                        .ToList();

                    defaultPaths.AddRange(customPathsList);
                }

                return defaultPaths.Distinct().ToList();
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Error getting custom disallow paths, using defaults");
                return defaultPaths;
            }
        }

        private async Task<List<string>> GetBlockedBotsAsync()
        {
            var defaultBlockedBots = new List<string>
            {
                "AhrefsBot",
                "MJ12bot",
                "SemrushBot",
                "DotBot",
                "MegaIndex",
                "BLEXBot",
                "LinkpadBot",
                "PaperLiBot",
                "MauiBot",
                "AlphaBot",
                "DeuSu",
                "BetaBot",
                "VoilaBot",
                "CCBot",
                "ChatGPT-User",
                "GPTBot",
                "Google-Extended",
                "anthropic-ai",
                "Claude-Web"
            };

            try
            {
                var customBots = await GetConfigValueAsync("SEO.Robots.BlockedBots", "");
                if (!string.IsNullOrEmpty(customBots))
                {
                    var customBotsList = customBots.Split(',', StringSplitOptions.RemoveEmptyEntries)
                        .Select(b => b.Trim())
                        .Where(b => !string.IsNullOrEmpty(b))
                        .ToList();

                    defaultBlockedBots.AddRange(customBotsList);
                }

                return defaultBlockedBots.Distinct().ToList();
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Error getting custom blocked bots, using defaults");
                return defaultBlockedBots;
            }
        }

        #endregion
    }
}