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

namespace NavisworksTransport.Core.Services
{
    /// <summary>
    /// 时标系统与TimeLiner集成 - 将时标数据转换为TimeLiner任务
    /// </summary>
    public class TimeTagTimeLinerIntegration
    {
        private readonly TimeTagService _timeTagService;
        private readonly TimeLinerIntegrationManager _timeLinerManager;

        public TimeTagTimeLinerIntegration(TimeTagService timeTagService)
        {
            _timeTagService = timeTagService ?? throw new ArgumentNullException(nameof(timeTagService));
            _timeLinerManager = new TimeLinerIntegrationManager();
        }

        /// <summary>
        /// TimeLiner 是否可用
        /// </summary>
        public bool IsTimeLinerAvailable => _timeLinerManager?.IsTimeLinerAvailable ?? false;

        /// <summary>
        /// 将时标配置导入为TimeLiner仿真任务
        /// </summary>
        /// <param name="profile">时标配置</param>
        /// <param name="route">路径</param>
        /// <param name="movingObject">运输物体（可选）</param>
        /// <param name="taskName">任务名称</param>
        /// <returns>是否成功</returns>
        public bool ImportToTimeLiner(TimeTagProfile profile, PathRoute route, ModelItem movingObject = null, string taskName = null)
        {
            try
            {
                if (profile == null || route == null)
                {
                    LogManager.Warning("导入TimeLiner失败: 配置或路径为空");
                    return false;
                }

                if (!IsTimeLinerAvailable)
                {
                    LogManager.Warning("TimeLiner 不可用，无法导入任务");
                    return false;
                }

                string name = taskName ?? $"{route.Name} - {profile.Name}";
                LogManager.Info($"开始导入TimeLiner: {name}");

                // 创建仿真数据
                var simulationData = CreateSimulationData(profile, route);
                
                // 计算持续时间
                var duration = TimeSpan.FromSeconds(profile.TotalTime);

                // 创建 TimeLiner 任务
                string taskId = null;
                if (movingObject != null)
                {
                    // 如果有选中物体，创建完整任务
                    taskId = _timeLinerManager.CreateTransportTask(name, simulationData.Waypoints.Select(w => w.Position).ToList(), duration, movingObject);
                }
                else
                {
                    // 没有选中物体，创建简单任务（仅信息展示）
                    taskId = CreateSimpleTimelinerTask(name, profile, route, duration);
                }

                if (taskId != null)
                {
                    LogManager.Info($"✓ TimeLiner 任务创建成功: {name}, 任务ID: {taskId}");
                    return true;
                }
                else
                {
                    LogManager.Error("TimeLiner 任务创建失败");
                    return false;
                }
            }
            catch (Exception ex)
            {
                LogManager.Error($"导入TimeLiner失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 创建简单的 TimeLiner 任务（无物体关联，仅信息展示）
        /// </summary>
        private string CreateSimpleTimelinerTask(string taskName, TimeTagProfile profile, PathRoute route, TimeSpan duration)
        {
            try
            {
                var doc = Application.ActiveDocument;
                var timeliner = doc?.GetTimeliner();
                if (timeliner == null) return null;

                var task = new TimelinerTask();
                task.DisplayName = $"运输任务：{taskName}";
                // Comments 属性是只读的，使用 DisplayName 包含更多信息
                task.DisplayName = $"运输任务：{taskName} ({profile.TotalTime:F1}s, {route.TotalLength:F1}m)";

                // 添加到 TimeLiner
                timeliner.TaskAddCopy(task);

                LogManager.Info($"✓ 简单 TimeLiner 任务创建成功: {taskName}");
                return Guid.NewGuid().ToString();
            }
            catch (Exception ex)
            {
                LogManager.Error($"创建简单 TimeLiner 任务失败: {ex.Message}");
                return null;
            }
        }

        /// <summary>
        /// 创建仿真数据 - 用于动画系统
        /// </summary>
        public SimulationData CreateSimulationData(TimeTagProfile profile, PathRoute route)
        {
            var data = new SimulationData
            {
                RouteName = route.Name,
                ProfileName = profile.Name,
                TotalTime = profile.TotalTime,
                TotalDistance = route.TotalLength,
                Waypoints = new List<SimulationWaypoint>()
            };

            if (profile.Events == null || profile.Events.Count == 0)
                return data;

            // 按距离排序的事件
            var events = profile.Events.OrderBy(e => e.Distance).ToList();

            // 生成仿真路径点
            for (int i = 0; i < events.Count; i++)
            {
                var evt = events[i];
                var point = FindPointAtDistance(route, evt.Distance);
                
                if (point != null)
                {
                    data.Waypoints.Add(new SimulationWaypoint
                    {
                        Time = evt.CumulativeTime,
                        Distance = evt.Distance,
                        Position = point.Position,
                        EventType = evt.Type,
                        EventName = evt.Name,
                        WaitTime = evt.WaitTime,
                        ActionTime = evt.ActionTime
                    });
                }
            }

            // 计算每段的实际速度
            CalculateSegmentSpeeds(data, profile);

            return data;
        }

        /// <summary>
        /// 获取指定距离处的路径点（插值）
        /// </summary>
        private PathPoint FindPointAtDistance(PathRoute route, double distance)
        {
            if (route?.Points == null || route.Points.Count == 0)
                return null;

            double accumulated = 0;
            for (int i = 0; i < route.Points.Count - 1; i++)
            {
                var p1 = route.Points[i];
                var p2 = route.Points[i + 1];
                double segLength = CalculateDistance(p1, p2);

                if (accumulated + segLength >= distance)
                {
                    double t = (distance - accumulated) / segLength;
                    return InterpolatePoint(p1, p2, t);
                }

                accumulated += segLength;
            }

            return route.Points[route.Points.Count - 1];
        }

        private double CalculateDistance(PathPoint p1, PathPoint p2)
        {
            double dx = p2.Position.X - p1.Position.X;
            double dy = p2.Position.Y - p1.Position.Y;
            double dz = p2.Position.Z - p1.Position.Z;
            return Math.Sqrt(dx * dx + dy * dy + dz * dz);
        }

        private PathPoint InterpolatePoint(PathPoint p1, PathPoint p2, double t)
        {
            return new PathPoint
            {
                Id = $"interp_{p1.Id}_{p2.Id}",
                Position = new Point3D(
                    p1.Position.X + (p2.Position.X - p1.Position.X) * t,
                    p1.Position.Y + (p2.Position.Y - p1.Position.Y) * t,
                    p1.Position.Z + (p2.Position.Z - p1.Position.Z) * t
                )
            };
        }

        private void CalculateSegmentSpeeds(SimulationData data, TimeTagProfile profile)
        {
            if (data.Waypoints.Count < 2) return;

            for (int i = 0; i < data.Waypoints.Count - 1; i++)
            {
                var wp1 = data.Waypoints[i];
                var wp2 = data.Waypoints[i + 1];
                
                double distance = wp2.Distance - wp1.Distance;
                double time = wp2.Time - wp1.Time - wp1.WaitTime - wp1.ActionTime;
                
                if (time > 0)
                {
                    wp1.Speed = distance / time;
                    wp1.SpeedRatio = wp1.Speed / profile.DefaultSpeed;
                }
            }
        }

        /// <summary>
        /// 生成仿真脚本（用于外部系统）
        /// </summary>
        public string GenerateSimulationScript(TimeTagProfile profile, PathRoute route)
        {
            var data = CreateSimulationData(profile, route);
            var sb = new System.Text.StringBuilder();
            
            sb.AppendLine("# Simulation Script");
            sb.AppendLine($"# Route: {data.RouteName}");
            sb.AppendLine($"# Profile: {data.ProfileName}");
            sb.AppendLine($"# Total Time: {data.TotalTime:F2}s");
            sb.AppendLine($"# Total Distance: {data.TotalDistance:F2}m");
            sb.AppendLine();

            foreach (var wp in data.Waypoints)
            {
                sb.AppendLine($"T={wp.Time:F2}s | D={wp.Distance:F2}m | " +
                    $"Pos=({wp.Position.X:F2}, {wp.Position.Y:F2}, {wp.Position.Z:F2}) | " +
                    $"Speed={wp.Speed:F2}m/s | {wp.EventType}");
            }

            return sb.ToString();
        }

        /// <summary>
        /// 导出仿真数据为JSON
        /// </summary>
        public string ExportSimulationJson(TimeTagProfile profile, PathRoute route)
        {
            var data = CreateSimulationData(profile, route);
            return ExportSimulationDataToJson(data);
        }

        private string ExportSimulationDataToJson(SimulationData data)
        {
            var sb = new System.Text.StringBuilder();
            sb.AppendLine("{");
            sb.AppendLine($"  \"routeName\": \"{EscapeJson(data.RouteName)}\",");
            sb.AppendLine($"  \"profileName\": \"{EscapeJson(data.ProfileName)}\",");
            sb.AppendLine($"  \"totalTime\": {data.TotalTime:F3},");
            sb.AppendLine($"  \"totalDistance\": {data.TotalDistance:F3},");
            sb.AppendLine("  \"waypoints\": [");

            for (int i = 0; i < data.Waypoints.Count; i++)
            {
                var wp = data.Waypoints[i];
                sb.AppendLine("    {");
                sb.AppendLine($"      \"time\": {wp.Time:F3},");
                sb.AppendLine($"      \"distance\": {wp.Distance:F3},");
                sb.Append($"      \"position\": {{\"x\": {wp.Position.X:F3}, \"y\": {wp.Position.Y:F3}, \"z\": {wp.Position.Z:F3}}},");
                sb.AppendLine();
                sb.AppendLine($"      \"eventType\": \"{wp.EventType}\",");
                sb.AppendLine($"      \"eventName\": \"{EscapeJson(wp.EventName)}\",");
                sb.AppendLine($"      \"waitTime\": {wp.WaitTime:F2},");
                sb.AppendLine($"      \"actionTime\": {wp.ActionTime:F2},");
                sb.AppendLine($"      \"speed\": {wp.Speed:F3},");
                sb.AppendLine($"      \"speedRatio\": {wp.SpeedRatio:F2}");
                sb.Append("    }");
                if (i < data.Waypoints.Count - 1) sb.Append(",");
                sb.AppendLine();
            }

            sb.AppendLine("  ]");
            sb.AppendLine("}");

            return sb.ToString();
        }

        private string EscapeJson(string str)
        {
            if (string.IsNullOrEmpty(str)) return "";
            return str.Replace("\\", "\\\\")
                     .Replace("\"", "\\\"")
                     .Replace("\n", "\\n")
                     .Replace("\r", "\\r")
                     .Replace("\t", "\\t");
        }
    }

    /// <summary>
    /// 仿真数据结构
    /// </summary>
    public class SimulationData
    {
        public string RouteName { get; set; }
        public string ProfileName { get; set; }
        public double TotalTime { get; set; }
        public double TotalDistance { get; set; }
        public List<SimulationWaypoint> Waypoints { get; set; }
    }

    /// <summary>
    /// 仿真路径点
    /// </summary>
    public class SimulationWaypoint
    {
        public double Time { get; set; }
        public double Distance { get; set; }
        public Point3D Position { get; set; }
        public EventType EventType { get; set; }
        public string EventName { get; set; }
        public double WaitTime { get; set; }
        public double ActionTime { get; set; }
        public double Speed { get; set; }
        public double SpeedRatio { get; set; }
    }
}
