using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Navisworks.Api;
using NavisworksTransport.Core.Models;
using NavisworksTransport.Utils;

namespace NavisworksTransport.Core.Services
{
    /// <summary>
    /// 时标计算器
    /// 基于事件节点和路径几何计算时间
    /// </summary>
    public class TimeTagCalculator
    {
        /// <summary>
        /// 计算时标配置的所有时间
        /// </summary>
        public void Calculate(TimeTagProfile profile, PathRoute route)
        {
            if (profile?.Events == null || profile.Events.Count < 2)
                return;

            // 按距离排序事件并更新原始列表
            var sortedEvents = profile.Events.OrderBy(e => e.Distance).ToList();
            
            // 清空并重新填充原始列表，确保顺序一致
            profile.Events.Clear();
            foreach (var evt in sortedEvents)
            {
                profile.Events.Add(evt);
            }
            
            double cumulativeTime = 0;

            for (int i = 0; i < profile.Events.Count; i++)
            {
                var evt = profile.Events[i];
                evt.SortOrder = i + 1;  // 更新排序序号
                evt.CumulativeTime = cumulativeTime;

                // 加上本事件的等待和动作时间
                cumulativeTime += evt.WaitTime + evt.ActionTime;

                // 计算到下一个事件的行驶时间
                if (i < profile.Events.Count - 1)
                {
                    var nextEvt = profile.Events[i + 1];
                    double segmentDistance = nextEvt.Distance - evt.Distance;
                    
                    if (segmentDistance > 0)
                    {
                        double segmentSpeed = CalculateSegmentSpeed(profile, route, evt, nextEvt);
                        double travelTime = segmentDistance / segmentSpeed;
                        cumulativeTime += travelTime;
                    }
                }
            }

            LogManager.Info($"[时标计算] 完成: {profile.Name}, 总时间: {cumulativeTime:F1}s, 事件数: {profile.Events.Count}");
        }

        /// <summary>
        /// 计算路段速度（简化模型）
        /// </summary>
        private double CalculateSegmentSpeed(TimeTagProfile profile, PathRoute route, 
            TimeTagEvent startEvent, TimeTagEvent endEvent)
        {
            // 基础速度
            double speed = profile.DefaultSpeed;

            // 检查是否包含圆弧段
            if (HasArcSegment(route, startEvent.Distance, endEvent.Distance))
            {
                speed *= profile.TurnSpeedRatio;
            }

            // 应用事件速度限制
            if (startEvent.LeaveSpeed.HasValue)
                speed = Math.Min(speed, startEvent.LeaveSpeed.Value);
            
            if (endEvent.ArriveSpeed.HasValue)
                speed = Math.Min(speed, endEvent.ArriveSpeed.Value);

            return Math.Max(speed, 0.1); // 最小速度限制
        }

        /// <summary>
        /// 检查路段是否包含圆弧
        /// </summary>
        private bool HasArcSegment(PathRoute route, double startDist, double endDist)
        {
            if (route?.Edges == null || !route.Edges.Any())
                return false;

            double currentDist = 0;
            foreach (var edge in route.Edges)
            {
                double edgeLength = edge.PhysicalLength;
                
                // 检查本路段是否与查询区间有重叠
                if (currentDist + edgeLength > startDist && currentDist < endDist)
                {
                    if (edge.SegmentType == PathSegmentType.Arc)
                        return true;
                }
                
                currentDist += edgeLength;
                if (currentDist > endDist) break;
            }
            
            return false;
        }

        /// <summary>
        /// 从路径自动生成事件节点
        /// </summary>
        public List<TimeTagEvent> GenerateDefaultEvents(PathRoute route)
        {
            var events = new List<TimeTagEvent>();
            
            if (route?.Points == null || route.Points.Count < 2)
                return events;

            var sortedPoints = route.Points.OrderBy(p => p.Index).ToList();
            double currentDistance = 0;

            // 起点
            events.Add(new TimeTagEvent
            {
                Type = EventType.Start,
                Name = "起点",
                Distance = 0,
                PointId = sortedPoints[0].Id,
                WaitTime = 0,
                ActionTime = 0
            });

            // 中间点：根据路径几何识别转弯点
            for (int i = 1; i < sortedPoints.Count - 1; i++)
            {
                var point = sortedPoints[i];
                var prevPoint = sortedPoints[i - 1];
                
                // 计算到当前点的距离
                double segmentDist = CalculateDistance(prevPoint.Position, point.Position);
                currentDistance += segmentDist;

                // 判断是否为转弯点（通过Edges判断）
                bool isTurn = IsTurnPoint(route, i);
                
                events.Add(new TimeTagEvent
                {
                    Type = isTurn ? EventType.Turn : EventType.Pass,
                    Name = isTurn ? $"转弯点 {i}" : $"途经点 {i}",
                    Distance = currentDistance,
                    PointId = point.Id,
                    WaitTime = 0,
                    ActionTime = isTurn ? 3.0 : 0 // 转弯默认3秒动作时间
                });
            }

            // 终点
            if (sortedPoints.Count > 1)
            {
                var lastPoint = sortedPoints[sortedPoints.Count - 1];
                var prevLastPoint = sortedPoints[sortedPoints.Count - 2];
                currentDistance += CalculateDistance(prevLastPoint.Position, lastPoint.Position);
                
                events.Add(new TimeTagEvent
                {
                    Type = EventType.End,
                    Name = "终点",
                    Distance = currentDistance,
                    PointId = lastPoint.Id,
                    WaitTime = 0,
                    ActionTime = 0
                });
            }

            return events;
        }

        /// <summary>
        /// 判断指定索引的点是否为转弯点
        /// </summary>
        private bool IsTurnPoint(PathRoute route, int pointIndex)
        {
            if (route?.Edges == null || route.Edges.Count == 0)
                return false;

            // 根据Edges判断：如果前后有圆弧边，则认为是转弯点
            var sortedPoints = route.Points.OrderBy(p => p.Index).ToList();
            if (pointIndex >= sortedPoints.Count) return false;

            var point = sortedPoints[pointIndex];
            
            // 查找与该点相关的圆弧边
            foreach (var edge in route.Edges)
            {
                if (edge.SegmentType == PathSegmentType.Arc)
                {
                    // 圆弧边连接了路径点，认为是转弯
                    if (edge.StartPointId == point.Id || edge.EndPointId == point.Id)
                        return true;
                }
            }
            
            return false;
        }

        /// <summary>
        /// 计算两点间距离（米）
        /// </summary>
        private double CalculateDistance(Point3D p1, Point3D p2)
        {
            var dx = p1.X - p2.X;
            var dy = p1.Y - p2.Y;
            var dz = p1.Z - p2.Z;
            var distInModelUnits = Math.Sqrt(dx * dx + dy * dy + dz * dz);
            return UnitsConverter.ConvertToMeters(distInModelUnits);
        }
    }
}
