using System;
using CounterDrone.Core.Models;

namespace CounterDrone.Core.Algorithms
{
    /// <summary>云团膨胀模型——根据弹药和环境参数计算各阶段半径、密度、膨胀时间</summary>
    public class CloudExpansionModel
    {
        private readonly AmmunitionSpec _ammo;
        private readonly CombatScene _env;
        private readonly float _initialRadius;

        public CloudExpansionModel(AmmunitionSpec ammo, CombatScene env)
        {
            _ammo = ammo;
            _env = env;

            var w = (float)ammo.BurstChargeKg;
            if (w <= 0)
                throw new ArgumentException($"BurstChargeKg 必须 > 0，实际: {w}", nameof(ammo));
            _initialRadius = 3.3f * (float)Math.Pow(w, 0.32);
        }

        /// <summary>Phase 1 爆轰初始半径 (m)</summary>
        public float InitialRadius => _initialRadius;
        /// <summary>Phase 2 结束时的有效半径</summary>
        public float TurbulentRadius => RadiusAt(Phase2Duration);

        /// <summary>湍流膨胀系数 k</summary>
        public float TurbulentExpansionK => (float)_ammo.TurbulentExpansionK;

        /// <summary>Phase 2 持续时间（s），从 AmmunitionSpec 读取</summary>
        public float Phase2Duration => (float)_ammo.Phase2Duration;

        /// <summary>指定时刻湍流膨胀半径 R(t) = R₀ + k√t</summary>
        public float RadiusAt(float elapsedSeconds)
        {
            if (elapsedSeconds <= 0) return _initialRadius;
            float p2 = Phase2Duration;
            bool inPhase3 = elapsedSeconds > p2;
            if (!inPhase3)
                return _initialRadius + TurbulentExpansionK * (float)Math.Sqrt(elapsedSeconds);

            // Phase 3: 高斯扩散
            float windSpeed = (float)_env.WindSpeed;
            float x = windSpeed * (elapsedSeconds - p2);
            if (x <= 0) return _initialRadius + TurbulentExpansionK * (float)Math.Sqrt(p2);
            var cls = Kinematics.GetStabilityClass((WeatherType)_env.WeatherType, windSpeed);
            float sY = Kinematics.SigmaY(cls, x);
            float sZ = Kinematics.SigmaZ(cls, x);
            float peakC = Kinematics.GaussianPeakConcentration((float)_ammo.SourceStrength, sY, sZ);
            float effConc = (float)_ammo.EffectiveConcentration;
            float rPhase2 = _initialRadius + TurbulentExpansionK * (float)Math.Sqrt(p2);
            if (peakC <= effConc) return rPhase2;
            float sigma = (sY + sZ) / 2f;
            return rPhase2 + sigma * (float)Math.Sqrt(2f * Math.Log(peakC / effConc));
        }

        /// <summary>指定时刻中心浓度</summary>
        public float DensityAt(float elapsedSeconds)
        {
            float r = RadiusAt(elapsedSeconds);
            float volume = (4f / 3f) * (float)Math.PI * r * r * r;
            if (volume <= 0.001f) return (float)_ammo.CoreDensity;
            return (float)_ammo.SourceStrength / volume;
        }

        /// <summary>覆盖指定距离需要的云团数量</summary>
        public int RoundsNeeded(float requiredCoverage, float? spacing = null)
        {
            float s = spacing ?? 2f * TurbulentRadius;
            if (s <= 0) return 1;
            int n = (int)Math.Ceiling(requiredCoverage / s);
            return n < 1 ? 1 : n;
        }

        /// <summary>达到指定半径所需时间 (s)</summary>
        public float TimeToReach(float radius)
        {
            if (radius <= _initialRadius) return 0;
            float k = TurbulentExpansionK;
            return (radius - _initialRadius) * (radius - _initialRadius) / (k * k);
        }
    }
}
