using System;
using System.Collections.Generic;

namespace EonaCat.LogStack.Policies
{
    /// <summary>
    /// Automatic batching policy for flows
    /// </summary>
    public sealed class AutoBatchingPolicy
    {
        public int MinimumBatchSize { get; set; } = 10;
        public int MaximumBatchSize { get; set; } = 100;
        public TimeSpan FlushInterval { get; set; } = TimeSpan.FromSeconds(5);
        public bool AdaptBatchSize { get; set; } = true;
        public double ScalingFactor { get; set; } = 1.5;
    }

    /// <summary>
    /// Automatic flow scaling policy
    /// </summary>
    public sealed class AutoScalingPolicy
    {
        public bool Enabled { get; set; } = true;
        public long BytesPerSecondThreshold { get; set; } = 10_000_000; // 10MB/s
        public double ErrorRateThreshold { get; set; } = 0.05; // 5%
        public TimeSpan EvaluationInterval { get; set; } = TimeSpan.FromSeconds(10);
        public int MaxBufferMultiplier { get; set; } = 5;
    }

    /// <summary>
    /// Automatic retention policy for log files
    /// </summary>
    public sealed class AutoRetentionPolicy
    {
        public bool Enabled { get; set; } = true;
        public TimeSpan MaxAge { get; set; } = TimeSpan.FromDays(30);
        public long MaxSize { get; set; } = 10_737_418_240; // 10GB
        public int MaxFileCount { get; set; } = 1000;
        public TimeSpan CleanupInterval { get; set; } = TimeSpan.FromHours(1);
        public bool CompressArchives { get; set; } = true;
    }

    /// <summary>
    /// Automatic optimization policy for performance
    /// </summary>
    public sealed class AutoOptimizationPolicy
    {
        public bool Enabled { get; set; } = true;
        public TimeSpan AnalysisInterval { get; set; } = TimeSpan.FromMinutes(5);
        public double SlowOperationThresholdPercentile { get; set; } = 0.95;
        public bool AutoAdjustBufferSizes { get; set; } = true;
        public bool AutoAdjustBatchSizes { get; set; } = true;
    }

    /// <summary>
    /// Collection of auto-policies for logger
    /// </summary>
    public sealed class AutoPolicies
    {
        public AutoBatchingPolicy Batching { get; } = new();
        public AutoScalingPolicy Scaling { get; } = new();
        public AutoRetentionPolicy Retention { get; } = new();
        public AutoOptimizationPolicy Optimization { get; } = new();
    }

    /// <summary>
    /// Policy engine for automatic optimization
    /// </summary>
    public sealed class AutoPolicyEngine
    {
        private readonly AutoPolicies _policies;
        private DateTime _lastAnalysis = DateTime.UtcNow;
        private DateTime _lastCleanup = DateTime.UtcNow;

        public AutoPolicyEngine(AutoPolicies policies = null)
        {
            _policies = policies ?? new AutoPolicies();
        }

        /// <summary>
        /// Evaluates policies and returns recommended actions
        /// </summary>
        public List<PolicyAction> EvaluatePolicies()
        {
            var actions = new List<PolicyAction>();
            var now = DateTime.UtcNow;

            // Check optimization policy
            if (_policies.Optimization.Enabled &&
                now - _lastAnalysis > _policies.Optimization.AnalysisInterval)
            {
                actions.Add(new PolicyAction
                {
                    Type = PolicyActionType.AnalyzePerformance,
                    Reason = "Scheduled performance analysis"
                });
                _lastAnalysis = now;
            }

            // Check retention policy
            if (_policies.Retention.Enabled &&
                now - _lastCleanup > _policies.Retention.CleanupInterval)
            {
                actions.Add(new PolicyAction
                {
                    Type = PolicyActionType.CleanupRetentionPolicy,
                    Reason = "Scheduled retention cleanup"
                });
                _lastCleanup = now;
            }

            return actions;
        }

        /// <summary>
        /// Gets all active policies as string
        /// </summary>
        public string GetPoliciesSummary()
        {
            var lines = new List<string>
            {
                "=== Auto-Policies Configuration ===",
                "",
                "Batching:",
                $"  Min Batch: {_policies.Batching.MinimumBatchSize}",
                $"  Max Batch: {_policies.Batching.MaximumBatchSize}",
                $"  Flush Interval: {_policies.Batching.FlushInterval.TotalSeconds:F1}s",
                $"  Adaptive: {_policies.Batching.AdaptBatchSize}",
                "",
                "Scaling:",
                $"  Enabled: {_policies.Scaling.Enabled}",
                $"  Throughput Threshold: {_policies.Scaling.BytesPerSecondThreshold / 1_000_000}MB/s",
                $"  Error Rate Threshold: {_policies.Scaling.ErrorRateThreshold:P}",
                "",
                "Retention:",
                $"  Enabled: {_policies.Retention.Enabled}",
                $"  Max Age: {_policies.Retention.MaxAge.TotalDays} days",
                $"  Max Size: {_policies.Retention.MaxSize / 1_073_741_824}GB",
                $"  Max Files: {_policies.Retention.MaxFileCount}",
                "",
                "Optimization:",
                $"  Enabled: {_policies.Optimization.Enabled}",
                $"  Analysis Interval: {_policies.Optimization.AnalysisInterval.TotalMinutes:F1}m",
                $"  Auto-Adjust Buffer: {_policies.Optimization.AutoAdjustBufferSizes}",
                $"  Auto-Adjust Batch: {_policies.Optimization.AutoAdjustBatchSizes}"
            };

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

    /// <summary>
    /// Policy action types
    /// </summary>
    public enum PolicyActionType
    {
        None = 0,
        AnalyzePerformance = 1,
        CleanupRetentionPolicy = 2,
        AdjustBatchSize = 3,
        AdjustBufferSize = 4,
        AlertHighErrorRate = 5,
        AlertHighThroughput = 6,
        CompressArchives = 7
    }

    /// <summary>
    /// Represents a policy action to execute
    /// </summary>
    public sealed class PolicyAction
    {
        public PolicyActionType Type { get; set; }
        public string? Reason { get; set; }
        public Dictionary<string, object> Parameters { get; set; } = new();
        public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    }
}
