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; } // km/h
        public List<Waypoint> Route { get; }
        public int CurrentWaypointIndex { get; private set; }
        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; } // 在云团中的累计暴露时间
        public float FormationOffsetX { get; set; }
        public float FormationOffsetY { get; set; }

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

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

            // 编队偏移
            ApplyFormationOffset(formationIndex, spacing, mode);
            PosX += FormationOffsetX;
            PosY += FormationOffsetY;
        }

        private void ApplyFormationOffset(int index, float spacing, FormationMode mode)
        {
            if (index == 0) return;
            var offset = spacing * index;
            switch (mode)
            {
                case FormationMode.Formation:
                    FormationOffsetY = offset; // 沿 Y 轴横队排列
                    break;
                case FormationMode.Swarm:
                    var rng = new Random(index * 137);
                    FormationOffsetX = (float)(rng.NextDouble() - 0.5) * spacing * 3;
                    FormationOffsetY = (float)(rng.NextDouble() - 0.5) * spacing * 3;
                    break;
            }
        }

        public void Update(float deltaTime, float windSpeed, WindDirection windDir)
        {
            if (Status != DroneStatus.Flying) return;
            if (Route.Count == 0) return;
            if (CurrentWaypointIndex >= Route.Count - 1)
            {
                Status = DroneStatus.ReachedTarget;
                return;
            }

            var target = Route[CurrentWaypointIndex + 1];
            var speedMs = TypicalSpeed / 3.6f;
            var dx = (float)(target.PosX - PosX);
            var dy = (float)(target.PosY - PosY);
            var dz = (float)(target.PosZ - PosZ);
            var dist = (float)Math.Sqrt(dx * dx + dy * dy + dz * dz);
            var step = speedMs * deltaTime;

            if (dist < 1.0f || step >= dist)
            {
                PosX = (float)target.PosX;
                PosY = (float)target.PosY;
                PosZ = (float)target.PosZ;
                CurrentWaypointIndex++;
                if (CurrentWaypointIndex >= Route.Count - 1)
                    Status = DroneStatus.ReachedTarget;
                return;
            }

            // 移动方向
            var ratio = step / dist;
            PosX += dx * ratio;
            PosY += dy * ratio;
            PosZ += dz * ratio;

            // 风偏
            (float wx, float wy, float wz) = Kinematics.WindToVector(windDir, windSpeed);
            PosX += wx * deltaTime;
            PosY += wy * deltaTime;
            PosZ += wz * deltaTime;
        }

        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;
        }
    }
}
