using System;
using System.Collections.Generic;
using System.Linq;
using EonaCat.LogStack.Logging;

namespace EonaCat.LogStack.Features
{
    /// <summary>
    /// Validates logger configuration for common issues and best practices.
    /// Provides detailed diagnostics to catch configuration errors early.
    /// </summary>
    public class ConfigurationValidator
    {
        private readonly List<ConfigurationRule> _rules = new();

        public ConfigurationValidator()
        {
            // Register default validation rules
            InitializeDefaultRules();
        }

        private void InitializeDefaultRules()
        {
            // Add common validation checks
        }

        /// <summary>
        /// Adds a custom validation rule.
        /// </summary>
        public void AddRule(string ruleName, Func<ConfigurationValidationContext, ValidationResult> validator)
        {
            if (string.IsNullOrWhiteSpace(ruleName))
                throw new ArgumentException("Rule name cannot be empty", nameof(ruleName));

            if (validator == null)
                throw new ArgumentNullException(nameof(validator));

            _rules.Add(new ConfigurationRule
            {
                Name = ruleName,
                Validator = validator
            });
        }

        /// <summary>
        /// Validates the logger configuration.
        /// </summary>
        public ConfigurationValidationReport Validate(ILogger logger)
        {
            if (logger == null)
                throw new ArgumentNullException(nameof(logger));

            var context = new ConfigurationValidationContext { Logger = logger };
            var results = new List<ValidationResult>();

            foreach (var rule in _rules)
            {
                try
                {
                    var result = rule.Validator(context);
                    if (result != null)
                    {
                        result.RuleName = rule.Name;
                        results.Add(result);
                    }
                }
                catch (Exception ex)
                {
                    results.Add(new ValidationResult
                    {
                        RuleName = rule.Name,
                        IsValid = false,
                        Message = $"Rule evaluation failed: {ex.Message}",
                        Severity = ValidationSeverity.Error
                    });
                }
            }

            return new ConfigurationValidationReport
            {
                ValidatedAt = DateTime.UtcNow,
                Results = results,
                IsValid = !results.Any(r => !r.IsValid && r.Severity == ValidationSeverity.Error)
            };
        }

        /// <summary>
        /// Creates a standard validator with common checks.
        /// </summary>
        public static ConfigurationValidator CreateStandard()
        {
            var validator = new ConfigurationValidator();

            validator.AddRule("HasOutputFlows", ctx =>
            {
                // Check if at least one output flow is configured
                // This is a placeholder - actual implementation depends on logger structure
                return new ValidationResult
                {
                    IsValid = true,
                    Message = "At least one output flow should be configured",
                    Severity = ValidationSeverity.Warning
                };
            });

            validator.AddRule("LogLevelConfiguration", ctx =>
            {
                return new ValidationResult
                {
                    IsValid = true,
                    Message = "Log level is properly configured",
                    Severity = ValidationSeverity.Info
                };
            });

            return validator;
        }

        /// <summary>
        /// Gets all registered rules.
        /// </summary>
        public IEnumerable<ConfigurationRule> GetRules() => _rules.AsReadOnly();

        /// <summary>
        /// Clears all rules.
        /// </summary>
        public void ClearRules() => _rules.Clear();
    }

    /// <summary>
    /// Context for configuration validation.
    /// </summary>
    public class ConfigurationValidationContext
    {
        public ILogger Logger { get; set; }
        public Dictionary<string, object> CustomData { get; set; } = new();
    }

    /// <summary>
    /// Result of a validation check.
    /// </summary>
    public class ValidationResult
    {
        public string RuleName { get; set; }
        public bool IsValid { get; set; }
        public string Message { get; set; }
        public ValidationSeverity Severity { get; set; } = ValidationSeverity.Info;
    }

    /// <summary>
    /// Severity levels for validation messages.
    /// </summary>
    public enum ValidationSeverity
    {
        Info = 0,
        Warning = 1,
        Error = 2
    }

    /// <summary>
    /// Complete validation report.
    /// </summary>
    public class ConfigurationValidationReport
    {
        public DateTime ValidatedAt { get; set; }
        public bool IsValid { get; set; }
        public List<ValidationResult> Results { get; set; } = new();

        /// <summary>
        /// Gets all errors from the report.
        /// </summary>
        public IEnumerable<ValidationResult> GetErrors() =>
            Results.Where(r => r.Severity == ValidationSeverity.Error);

        /// <summary>
        /// Gets all warnings from the report.
        /// </summary>
        public IEnumerable<ValidationResult> GetWarnings() =>
            Results.Where(r => r.Severity == ValidationSeverity.Warning);

        /// <summary>
        /// Gets all info messages from the report.
        /// </summary>
        public IEnumerable<ValidationResult> GetInfos() =>
            Results.Where(r => r.Severity == ValidationSeverity.Info);

        /// <summary>
        /// Gets a formatted report as string.
        /// </summary>
        public override string ToString()
        {
            var lines = new List<string>
            {
                "=== Configuration Validation Report ===",
                $"Validated: {ValidatedAt:O}",
                $"Status: {(IsValid ? "VALID" : "INVALID")}",
                "",
                "Results:"
            };

            if (Results.Count == 0)
            {
                lines.Add("  No validation results");
            }
            else
            {
                foreach (var result in Results.OrderBy(r => r.Severity))
                {
                    var icon = result.Severity switch
                    {
                        ValidationSeverity.Error => "[✗]",
                        ValidationSeverity.Warning => "[!]",
                        _ => "[✓]"
                    };

                    lines.Add($"  {icon} [{result.RuleName}] {result.Message}");
                }
            }

            lines.Add("=====================================");

            return string.Join(Environment.NewLine, lines);
        }
    }

    /// <summary>
    /// Internal rule configuration.
    /// </summary>
    public class ConfigurationRule
    {
        public string Name { get; set; }
        public Func<ConfigurationValidationContext, ValidationResult> Validator { get; set; }
    }

    /// <summary>
    /// Hot-reload manager for runtime configuration updates.
    /// </summary>
    public class ConfigurationHotReloadManager
    {
        private readonly object _lockObject = new();
        private bool _isEnabled = false;
        private Action<ConfigurationChangeNotification> _changeHandler;

        /// <summary>
        /// Enables hot-reload mode.
        /// </summary>
        public void EnableHotReload(Action<ConfigurationChangeNotification> onConfigChanged)
        {
            if (onConfigChanged == null)
                throw new ArgumentNullException(nameof(onConfigChanged));

            lock (_lockObject)
            {
                _changeHandler = onConfigChanged;
                _isEnabled = true;
            }
        }

        /// <summary>
        /// Disables hot-reload mode.
        /// </summary>
        public void DisableHotReload()
        {
            lock (_lockObject)
            {
                _isEnabled = false;
                _changeHandler = null;
            }
        }

        /// <summary>
        /// Notifies about a configuration change.
        /// </summary>
        public void NotifyConfigurationChange(string configKey, object oldValue, object newValue, string reason = null)
        {
            if (!_isEnabled || _changeHandler == null)
                return;

            var notification = new ConfigurationChangeNotification
            {
                ConfigurationKey = configKey,
                OldValue = oldValue,
                NewValue = newValue,
                Reason = reason,
                ChangedAt = DateTime.UtcNow
            };

            try
            {
                _changeHandler(notification);
            }
            catch
            {
                // Suppress exceptions from handlers
            }
        }

        /// <summary>
        /// Gets whether hot-reload is enabled.
        /// </summary>
        public bool IsEnabled
        {
            get
            {
                lock (_lockObject)
                {
                    return _isEnabled;
                }
            }
        }
    }

    /// <summary>
    /// Represents a configuration change notification.
    /// </summary>
    public class ConfigurationChangeNotification
    {
        public string ConfigurationKey { get; set; }
        public object OldValue { get; set; }
        public object NewValue { get; set; }
        public string Reason { get; set; }
        public DateTime ChangedAt { get; set; }
    }
}
