using System.Collections.Generic;
using UnityEngine;

namespace IGP.UnitySDK.Core
{
    /// <summary>
    /// RTT (Round-Trip Time) 统计信息
    /// 用于测量和监控网络延迟
    /// </summary>
    public class IGPRTTStats
    {
        private readonly List<RttSample> samples = new List<RttSample>();
        private const int MaxSamples = 100; // 保留最近100个样本

        private float stableCumulativeSum = 0f;
        private float rawCumulativeSum = 0f;
        private int stableSampleCount;
        private int congestedSampleCount;

        private readonly struct RttSample
        {
            public RttSample(float rtt, bool congested)
            {
                Rtt = rtt;
                Congested = congested;
            }

            public float Rtt { get; }
            public bool Congested { get; }
        }

        /// <summary>
        /// 最小RTT（秒）
        /// </summary>
        public float MinRTT { get; private set; } = float.MaxValue;

        /// <summary>
        /// 最大RTT（秒）
        /// </summary>
        public float MaxRTT { get; private set; } = 0f;

        /// <summary>
        /// 平均RTT（秒）
        /// </summary>
        public float AvgRTT { get; private set; } = 0f;

        /// <summary>
        /// 原始平均RTT（秒），包含进入 KCP 发送队列时已经拥塞的心跳样本。
        /// </summary>
        public float RawAvgRTT { get; private set; } = 0f;

        /// <summary>
        /// 最后一次RTT（秒）
        /// </summary>
        public float LastRTT { get; private set; } = 0f;

        /// <summary>
        /// 最后一次样本是否在发送时已经遇到 KCP 排队。
        /// </summary>
        public bool LastSampleCongested { get; private set; }

        /// <summary>
        /// 原始样本数量。
        /// </summary>
        public int SampleCount => samples.Count;

        /// <summary>
        /// 未被 KCP 排队污染的稳定样本数量。
        /// </summary>
        public int StableSampleCount => stableSampleCount;

        /// <summary>
        /// 因 KCP 发送队列非空而被标记为拥塞的样本数量。
        /// </summary>
        public int CongestedSampleCount => congestedSampleCount;

        /// <summary>
        /// 添加RTT样本
        /// </summary>
        /// <param name="rtt">RTT值（秒）</param>
        public void AddSample(float rtt)
        {
            AddSample(rtt, sampleIsCongested: false);
        }

        /// <summary>
        /// 添加RTT样本，并标记这个心跳样本是否已经被 KCP 发送队列污染。
        /// </summary>
        /// <param name="rtt">RTT值（秒）</param>
        /// <param name="sampleIsCongested">心跳发送时 KCP 队列是否已经非空</param>
        public void AddSample(float rtt, bool sampleIsCongested)
        {
            LastRTT = rtt;
            LastSampleCongested = sampleIsCongested;
            MinRTT = Mathf.Min(MinRTT, rtt);
            MaxRTT = Mathf.Max(MaxRTT, rtt);

            AddRollingSample(rtt, sampleIsCongested);
            RawAvgRTT = rawCumulativeSum / samples.Count;

            // AvgRTT 保持给接入侧展示“网络基线”的口径；如果暂时没有干净样本，则回退到原始平均。
            AvgRTT = stableSampleCount > 0
                ? stableCumulativeSum / stableSampleCount
                : RawAvgRTT;
        }

        private void AddRollingSample(float rtt, bool congested)
        {
            samples.Add(new RttSample(rtt, congested));
            rawCumulativeSum += rtt;
            if (congested)
            {
                congestedSampleCount++;
            }
            else
            {
                stableCumulativeSum += rtt;
                stableSampleCount++;
            }

            if (samples.Count <= MaxSamples)
            {
                return;
            }

            var removed = samples[0];
            rawCumulativeSum -= removed.Rtt;
            if (removed.Congested)
            {
                congestedSampleCount--;
            }
            else
            {
                stableCumulativeSum -= removed.Rtt;
                stableSampleCount--;
            }

            samples.RemoveAt(0);
        }

        /// <summary>
        /// 重置所有统计信息
        /// </summary>
        public void Reset()
        {
            samples.Clear();
            stableCumulativeSum = 0f;
            rawCumulativeSum = 0f;
            stableSampleCount = 0;
            congestedSampleCount = 0;
            MinRTT = float.MaxValue;
            MaxRTT = 0f;
            AvgRTT = 0f;
            RawAvgRTT = 0f;
            LastRTT = 0f;
            LastSampleCongested = false;
        }
        
        /// <summary>
        /// 获取统计信息摘要
        /// </summary>
        /// <returns>(min, max, avg, last, count)</returns>
        public (float min, float max, float avg, float last, int count) GetStats()
        {
            return (MinRTT, MaxRTT, AvgRTT, LastRTT, SampleCount);
        }
        
        /// <summary>
        /// 获取网络质量评级
        /// </summary>
        /// <returns>优秀/良好/一般/较差/很差</returns>
        public string GetQuality()
        {
            float avgMs = AvgRTT * 1000f;
            
            if (avgMs < 20f) return "优秀";
            if (avgMs < 50f) return "良好";
            if (avgMs < 100f) return "一般";
            if (avgMs < 200f) return "较差";
            return "很差";
        }
        
        /// <summary>
        /// 获取质量颜色
        /// </summary>
        /// <returns>Unity Color</returns>
        public Color GetQualityColor()
        {
            float avgMs = AvgRTT * 1000f;
            
            if (avgMs < 20f) return Color.green;        // 优秀
            if (avgMs < 50f) return Color.yellow;       // 良好
            if (avgMs < 100f) return new Color(1f, 0.5f, 0f); // 一般（橙色）
            if (avgMs < 200f) return new Color(1f, 0.3f, 0f); // 较差（深橙）
            return Color.red;                            // 很差
        }
        
        /// <summary>
        /// 转换为字符串（用于日志）
        /// </summary>
        public override string ToString()
        {
            if (SampleCount == 0)
            {
                return "RTT: No samples";
            }

            return $"RTT: last={LastRTT*1000:F1}ms, avg={AvgRTT*1000:F1}ms, " +
                   $"min={MinRTT*1000:F1}ms, max={MaxRTT*1000:F1}ms, samples={SampleCount}";
        }
    }
}
