using System;
using System.Collections.Generic;
using CounterDrone.Core.Algorithms;
using CounterDrone.Core.Models;

namespace CounterDrone.Core.Simulation
{
    public class DroneEntity
    {
        public string Id { get; }
        public string GroupId { get; }
        public TargetType TargetType { get; }
        public PowerType PowerType { get; }
        public float Wingspan { get; }
        public float TypicalSpeed { get; }
        public List<Waypoint> Route { get; }
        public float PosX { get; private set; }
        public float PosY { get; private set; }
        public float PosZ { get; private set; }
        public float Hp { get; private set; } = 1.0f;
        public DroneStatus Status { get; private set; } = DroneStatus.Flying;
        public float ExposureTime { get; set; }
        /// <summary>上一帧位置（路径积分用）</summary>
        public float PrevX { get; private set; }
        public float PrevY { get; private set; }
        public float PrevZ { get; private set; }
        /// <summary>沿航路已飞行弧长（米），由 RouteGeometry 驱动</summary>
        private float _traveledArc;

        public DroneEntity(string id, string groupId, TargetConfig config, List<Waypoint> route,
            int formationIndex, float lateralSpacing, int longitudinalIndex, float longitudinalSpacing, FormationMode mode)
        {
            Id = id;
            GroupId = groupId;
            TargetType = (TargetType)config.TargetType;
            PowerType = (PowerType)config.PowerType;
            Wingspan = (float)config.Wingspan;
            TypicalSpeed = (float)config.TypicalSpeed;
            Route = route;

            // 编队偏移应用到航点上（每架独立航路）
            float latOffset = 0, longOffset = 0;
            switch (mode)
            {
                case FormationMode.Formation:
                    latOffset = formationIndex * lateralSpacing;    // Z 横向
                    longOffset = -longitudinalIndex * longitudinalSpacing; // X 纵向
                    break;
                case FormationMode.Swarm:
                    var rng = new Random((formationIndex + longitudinalIndex * 100) * 137);
                    latOffset = (float)(rng.NextDouble() - 0.5) * lateralSpacing * 3;
                    longOffset = (float)(rng.NextDouble() - 0.5) * lateralSpacing * 3;
                    break;
            }

            // 克隆航点并加偏移
            var offsetRoute = new List<Waypoint>();
            foreach (var wp in route)
            {
                offsetRoute.Add(new Waypoint
                {
                    PosX = wp.PosX + longOffset,
                    PosY = wp.PosY,
                    PosZ = wp.PosZ + latOffset,
                    Altitude = wp.Altitude,
                    Speed = wp.Speed,
                });
            }
            Route = offsetRoute;

            if (offsetRoute.Count > 0)
            {
                PosX = (float)offsetRoute[0].PosX;
                PosY = (float)offsetRoute[0].PosY;
                PosZ = (float)offsetRoute[0].PosZ;
            }
        }

        public void SavePreviousPosition()
        {
            PrevX = PosX; PrevY = PosY; PrevZ = PosZ;
        }

        public void Update(float deltaTime)
        {
            if (Status != DroneStatus.Flying) return;
            if (Route.Count == 0) return;

            // 运动模型统一在 RouteGeometry：弧长推进 + 位置查询。
            // 无人机严格按航路匀速飞行。无人机不受风偏影响（真实无人机有飞控修正航向），
            // 但云团受风偏影响（见 SimulationEngine 毁伤判定的云团参考系修正）。
            float totalLen = RouteGeometry.TotalLength(Route);
            if (totalLen <= 0f)
            {
                Status = DroneStatus.ReachedTarget;
                return;
            }

            float speedMs = TypicalSpeed / 3.6f;
            _traveledArc += speedMs * deltaTime;

            if (_traveledArc >= totalLen)
            {
                var end = Route[^1];
                PosX = (float)end.PosX;
                PosY = (float)end.PosY;
                PosZ = (float)end.PosZ;
                Status = DroneStatus.ReachedTarget;
                return;
            }

            var (x, y, z) = RouteGeometry.PositionAt(Route, _traveledArc);
            PosX = x;
            PosY = y;
            PosZ = z;
        }

        public void ApplyDamage(float damage)
        {
            if (Status != DroneStatus.Flying) return;
            Hp -= damage;
            if (Hp <= 0)
            {
                Hp = 0;
                Status = DroneStatus.Destroyed;
            }
        }

        public void MarkZoneIntruded()
        {
            Status = DroneStatus.ZoneIntruded;
        }
    }
}
