using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using CounterDrone.Core.Models;

namespace CounterDrone.Core
{
    /// <summary>
    /// 统一默认数据 — 弹药、编队、火力单元、无人机、探测设备、天气的预设库。
    /// 所有默认数据集中在 data/defaults.json，通过本类统一加载。
    /// </summary>
    public class DefaultData
    {
        public string Version { get; set; } = "0";
        public List<AmmunitionSpec> Ammunition { get; set; } = new();
        public List<FormationTemplate> Formations { get; set; } = new();
        public List<RoutePreset> Routes { get; set; } = new();
        public List<FireUnitTemplate> FireUnits { get; set; } = new();
        public List<TargetPreset> Targets { get; set; } = new();
        public List<DetectionPreset> DetectionEquipment { get; set; } = new();
        public List<WeatherPreset> Weather { get; set; } = new();

        /// <summary>从 data/defaults.json 加载。文件缺失或解析失败即抛异常。</summary>
        public static DefaultData Load(IPathProvider paths)
        {
            var jsonPath = Path.Combine(paths.GetDataRoot(), "defaults.json");
            if (!File.Exists(jsonPath))
                throw new FileNotFoundException($"默认数据文件未找到: {jsonPath}");

            var opts = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
            var data = JsonSerializer.Deserialize<DefaultData>(File.ReadAllText(jsonPath), opts)
                ?? throw new InvalidOperationException($"默认数据文件解析失败: {jsonPath}");

            Validate(data, jsonPath);
            return data;
        }

        /// <summary>从 JSON 字符串解析（测试用）</summary>
        public static DefaultData FromJson(string json)
        {
            var opts = new JsonSerializerOptions { PropertyNameCaseInsensitive = true };
            var data = JsonSerializer.Deserialize<DefaultData>(json, opts)
                ?? throw new InvalidOperationException("默认数据 JSON 解析失败");
            Validate(data, "<string>");
            return data;
        }

        private static void Validate(DefaultData data, string source)
        {
            if (data.Ammunition == null || data.Ammunition.Count == 0)
                throw new InvalidOperationException($"默认数据缺少 ammunition: {source}");
            if (data.Formations == null || data.Formations.Count == 0)
                throw new InvalidOperationException($"默认数据缺少 formations: {source}");
            if (data.Routes == null || data.Routes.Count == 0)
                throw new InvalidOperationException($"默认数据缺少 routes: {source}");
            if (data.FireUnits == null || data.FireUnits.Count == 0)
                throw new InvalidOperationException($"默认数据缺少 fireUnits: {source}");
            if (data.Targets == null || data.Targets.Count == 0)
                throw new InvalidOperationException($"默认数据缺少 targets: {source}");
            if (data.Weather == null || data.Weather.Count == 0)
                throw new InvalidOperationException($"默认数据缺少 weather: {source}");
            if (data.DetectionEquipment == null)
                data.DetectionEquipment = new();
        }
    }

    /// <summary>编队模板</summary>
    public class FormationTemplate
    {
        public string Id { get; set; } = "";
        public string Name { get; set; } = "";
        public int FormationMode { get; set; }
        public int LateralCount { get; set; } = 1;
        public int LongitudinalCount { get; set; } = 1;
        public double LateralSpacing { get; set; }
        public double LongitudinalSpacing { get; set; }

        public RoutePlan ToRoutePlan()
        {
            return new RoutePlan
            {
                FormationMode = FormationMode,
                LateralCount = LateralCount,
                LongitudinalCount = LongitudinalCount,
                LateralSpacing = LateralSpacing,
                LongitudinalSpacing = LongitudinalSpacing,
            };
        }
    }

    /// <summary>火力单元模板</summary>
    public class FireUnitTemplate
    {
        public string Id { get; set; } = "";
        public string Name { get; set; } = "";
        public int PlatformType { get; set; }
        public int GunCount { get; set; } = 1;
        public int ChannelsPerGun { get; set; } = 1;
        public double ChannelInterval { get; set; } = 1.0;
        public double Cooldown { get; set; } = 5.0;
        public double AmmoChangeTime { get; set; } = 30.0;
        public double MuzzleVelocity { get; set; }
        public double CruiseSpeed { get; set; }
        public double ReleaseAltitude { get; set; }
        public List<int> AmmoTypes { get; set; } = new();
        public double RadarRange { get; set; }
        public double EORange { get; set; }
        public double IRRange { get; set; }
        // 3D 球冠几何（缺失时退化 2D）
        public double? MinElevation { get; set; }
        public double? MaxElevation { get; set; }
        public double? MinDetectAlt { get; set; }
        public double? MaxDetectAlt { get; set; }

        public EquipmentDeployment ToEquipmentDeployment(AerosolType ammoType, int quantity,
            double posX, double posY, double posZ)
        {
            return new EquipmentDeployment
            {
                EquipmentRole = (int)Models.EquipmentRole.LaunchPlatform,
                PlatformType = PlatformType,
                Quantity = quantity,
                PositionX = posX,
                PositionY = posY,
                PositionZ = posZ,
                AerosolType = (int)ammoType,
                MunitionCount = GunCount * ChannelsPerGun * quantity,
                GunCount = GunCount,
                ChannelsPerGun = ChannelsPerGun,
                ChannelInterval = ChannelInterval,
                Cooldown = Cooldown,
                MuzzleVelocity = MuzzleVelocity > 0 ? MuzzleVelocity : null,
                CruiseSpeed = CruiseSpeed > 0 ? CruiseSpeed : null,
                ReleaseAltitude = ReleaseAltitude > 0 ? ReleaseAltitude : null,
                RadarRange = RadarRange > 0 ? RadarRange : null,
                EORange = EORange > 0 ? EORange : null,
                IRRange = IRRange > 0 ? IRRange : null,
                MinElevation = MinElevation,
                MaxElevation = MaxElevation,
                MinDetectAlt = MinDetectAlt,
                MaxDetectAlt = MaxDetectAlt,
            };
        }
    }

    /// <summary>无人机/威胁目标预设</summary>
    public class TargetPreset
    {
        public string Id { get; set; } = "";
        public string Name { get; set; } = "";
        public int TargetType { get; set; }
        public int PowerType { get; set; }
        public double Wingspan { get; set; }
        public double TypicalSpeed { get; set; }
        public double TypicalAltitude { get; set; }

        public TargetConfig ToTargetConfig(string waveId = "default")
        {
            return new TargetConfig
            {
                WaveId = waveId,
                TargetType = TargetType,
                PowerType = PowerType,
                Quantity = 1,
                Wingspan = Wingspan,
                TypicalSpeed = TypicalSpeed,
                TypicalAltitude = TypicalAltitude,
            };
        }
    }

    /// <summary>独立探测设备预设</summary>
    public class DetectionPreset
    {
        public string Id { get; set; } = "";
        public string Name { get; set; } = "";
        public double RadarRange { get; set; }
        public double EORange { get; set; }
        public double IRRange { get; set; }
        public double Accuracy { get; set; } = 50.0;
        // 3D 球冠几何（缺失时退化 2D）
        public double? MinElevation { get; set; }
        public double? MaxElevation { get; set; }
        public double? MinDetectAlt { get; set; }
        public double? MaxDetectAlt { get; set; }

        public EquipmentDeployment ToEquipmentDeployment(double posX, double posY, double posZ)
        {
            return new EquipmentDeployment
            {
                EquipmentRole = (int)Models.EquipmentRole.Detection,
                Quantity = 1,
                PositionX = posX,
                PositionY = posY,
                PositionZ = posZ,
                RadarRange = RadarRange > 0 ? RadarRange : null,
                EORange = EORange > 0 ? EORange : null,
                IRRange = IRRange > 0 ? IRRange : null,
                DetectionAccuracy = Accuracy > 0 ? Accuracy : null,
                MinElevation = MinElevation,
                MaxElevation = MaxElevation,
                MinDetectAlt = MinDetectAlt,
                MaxDetectAlt = MaxDetectAlt,
            };
        }
    }

    /// <summary>天气/场景预设</summary>
    public class WeatherPreset
    {
        public string Id { get; set; } = "";
        public string Name { get; set; } = "";
        public int WeatherType { get; set; }
        public double WindSpeed { get; set; }
        public int WindDirection { get; set; }
        public double Temperature { get; set; } = 20.0;
        public double Humidity { get; set; } = 60.0;
        public double Pressure { get; set; } = 1013.0;
        public double Visibility { get; set; } = 5000.0;

        public CombatScene ToCombatScene()
        {
            return new CombatScene
            {
                WeatherType = WeatherType,
                WindSpeed = WindSpeed,
                WindDirection = WindDirection,
                Temperature = Temperature,
                Humidity = Humidity,
                Pressure = Pressure,
                Visibility = Visibility,
            };
        }
    }

    /// <summary>航线预设 — 航路点坐标集合，速度由目标 TypicalSpeed 提供</summary>
    public class RoutePreset
    {
        public string Id { get; set; } = "";
        public string Name { get; set; } = "";
        public List<WaypointCoord> Waypoints { get; set; } = new();

        public List<Waypoint> ToWaypoints(double speed)
        {
            var list = new List<Waypoint>();
            foreach (var w in Waypoints)
                list.Add(new Waypoint
                {
                    PosX = w.X, PosY = w.Y, PosZ = w.Z,
                    Altitude = w.Y, Speed = speed,
                });
            return list;
        }
    }

    public class WaypointCoord
    {
        public double X { get; set; }
        public double Y { get; set; }
        public double Z { get; set; }
    }
}
